2023-10-20 00:38:41 +00:00
|
|
|
use std::net;
|
|
|
|
use std::path::PathBuf;
|
|
|
|
use std::str::FromStr;
|
2021-10-14 09:58:09 +00:00
|
|
|
|
2021-10-13 15:12:13 +00:00
|
|
|
use log::info;
|
2022-06-07 22:30:56 +00:00
|
|
|
use serde::Serialize;
|
|
|
|
|
2020-12-07 12:35:24 +00:00
|
|
|
use tokio::sync::watch;
|
|
|
|
|
2023-10-20 00:38:41 +00:00
|
|
|
use tokio_unix_tcp::{NamedSocketAddr, UnixSocketAddr};
|
|
|
|
|
2022-07-22 11:06:10 +00:00
|
|
|
use crate::netapp::*;
|
2020-12-12 20:14:15 +00:00
|
|
|
|
2020-12-02 19:12:24 +00:00
|
|
|
/// Utility function: encodes any serializable value in MessagePack binary format
|
|
|
|
/// using the RMP library.
|
|
|
|
///
|
|
|
|
/// Field names and variant names are included in the serialization.
|
|
|
|
/// This is used internally by the netapp communication protocol.
|
2022-07-21 17:05:51 +00:00
|
|
|
pub fn rmp_to_vec_all_named<T>(val: &T) -> Result<Vec<u8>, rmp_serde::encode::Error>
|
2020-12-02 12:30:47 +00:00
|
|
|
where
|
2022-07-21 17:05:51 +00:00
|
|
|
T: Serialize + ?Sized,
|
2020-12-02 12:30:47 +00:00
|
|
|
{
|
|
|
|
let mut wr = Vec::with_capacity(128);
|
2023-06-13 15:22:33 +00:00
|
|
|
let mut se = rmp_serde::Serializer::new(&mut wr).with_struct_map();
|
2022-06-07 22:30:56 +00:00
|
|
|
val.serialize(&mut se)?;
|
2022-07-21 17:05:51 +00:00
|
|
|
Ok(wr)
|
2020-12-02 12:30:47 +00:00
|
|
|
}
|
2020-12-07 12:35:24 +00:00
|
|
|
|
|
|
|
/// This async function returns only when a true signal was received
|
|
|
|
/// from a watcher that tells us when to exit.
|
2021-10-14 09:35:05 +00:00
|
|
|
///
|
2020-12-07 12:35:24 +00:00
|
|
|
/// Usefull in a select statement to interrupt another
|
|
|
|
/// future:
|
2021-10-13 16:05:49 +00:00
|
|
|
/// ```ignore
|
2020-12-07 12:35:24 +00:00
|
|
|
/// select!(
|
|
|
|
/// _ = a_long_task() => Success,
|
|
|
|
/// _ = await_exit(must_exit) => Interrupted,
|
|
|
|
/// )
|
|
|
|
/// ```
|
|
|
|
pub async fn await_exit(mut must_exit: watch::Receiver<bool>) {
|
2021-10-12 11:07:34 +00:00
|
|
|
while !*must_exit.borrow_and_update() {
|
|
|
|
if must_exit.changed().await.is_err() {
|
|
|
|
break;
|
2020-12-07 12:35:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-10-13 15:12:13 +00:00
|
|
|
|
2021-10-14 09:35:05 +00:00
|
|
|
/// Creates a watch that contains `false`, and that changes
|
|
|
|
/// to `true` when a Ctrl+C signal is received.
|
2021-10-13 15:12:13 +00:00
|
|
|
pub fn watch_ctrl_c() -> watch::Receiver<bool> {
|
|
|
|
let (send_cancel, watch_cancel) = watch::channel(false);
|
|
|
|
tokio::spawn(async move {
|
|
|
|
tokio::signal::ctrl_c()
|
|
|
|
.await
|
|
|
|
.expect("failed to install CTRL+C signal handler");
|
|
|
|
info!("Received CTRL+C, shutting down.");
|
|
|
|
send_cancel.send(true).unwrap();
|
|
|
|
});
|
|
|
|
watch_cancel
|
|
|
|
}
|
2021-10-14 09:58:09 +00:00
|
|
|
|
|
|
|
/// Parse a peer's address including public key, written in the format:
|
2023-10-20 00:38:41 +00:00
|
|
|
/// `<public key hex>@<ip>:<port>` or
|
|
|
|
/// `<public key hex>@<path>` for unix domain sockets
|
|
|
|
pub fn parse_peer_addr(peer: &str) -> Option<(NodeID, NamedSocketAddr)> {
|
2021-10-14 09:58:09 +00:00
|
|
|
let delim = peer.find('@')?;
|
2023-10-20 00:38:41 +00:00
|
|
|
let (key, host) = peer.split_at(delim);
|
2023-01-31 22:57:33 +00:00
|
|
|
let pubkey = NodeID::from_slice(&hex::decode(key).ok()?)?;
|
2023-10-20 00:38:41 +00:00
|
|
|
let host = NamedSocketAddr::from_str(&host[1..]).ok()?;
|
|
|
|
Some((pubkey, host))
|
2021-10-14 09:58:09 +00:00
|
|
|
}
|
2021-10-18 10:39:19 +00:00
|
|
|
|
|
|
|
/// Parse and resolve a peer's address including public key, written in the format:
|
2023-10-20 00:38:41 +00:00
|
|
|
/// `<public key hex>@<ip or hostname>:<port>` or
|
|
|
|
/// `<public key hex>@<path>` for unix domain sockets
|
|
|
|
pub fn parse_and_resolve_peer_addr(peer: &str) -> Option<(NodeID, Vec<NamedSocketAddr>)> {
|
2021-10-18 10:39:19 +00:00
|
|
|
let delim = peer.find('@')?;
|
|
|
|
let (key, host) = peer.split_at(delim);
|
2023-01-31 22:57:33 +00:00
|
|
|
let pubkey = NodeID::from_slice(&hex::decode(key).ok()?)?;
|
2023-10-20 00:38:41 +00:00
|
|
|
let host = &host[1..];
|
|
|
|
let hosts = if UnixSocketAddr::is_pathname(host) {
|
|
|
|
vec![PathBuf::from_str(host).unwrap().into()]
|
|
|
|
} else {
|
|
|
|
use std::net::ToSocketAddrs;
|
|
|
|
|
|
|
|
host.parse::<net::SocketAddr>()
|
|
|
|
.ok()?
|
|
|
|
.to_socket_addrs()
|
|
|
|
.ok()?
|
|
|
|
.map(NamedSocketAddr::Inet)
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
};
|
|
|
|
|
2021-10-18 10:41:46 +00:00
|
|
|
if hosts.is_empty() {
|
|
|
|
return None;
|
|
|
|
}
|
2021-10-18 10:39:19 +00:00
|
|
|
Some((pubkey, hosts))
|
|
|
|
}
|
2022-09-14 13:45:05 +00:00
|
|
|
|
|
|
|
/// async version of parse_and_resolve_peer_addr
|
2023-10-20 00:38:41 +00:00
|
|
|
pub async fn parse_and_resolve_peer_addr_async(
|
|
|
|
peer: &str,
|
|
|
|
) -> Option<(NodeID, Vec<NamedSocketAddr>)> {
|
2022-09-14 13:45:05 +00:00
|
|
|
let delim = peer.find('@')?;
|
|
|
|
let (key, host) = peer.split_at(delim);
|
2023-01-31 22:57:33 +00:00
|
|
|
let pubkey = NodeID::from_slice(&hex::decode(key).ok()?)?;
|
2023-10-20 00:38:41 +00:00
|
|
|
let host = &host[1..];
|
|
|
|
let hosts = if UnixSocketAddr::is_pathname(host) {
|
|
|
|
vec![PathBuf::from_str(host).unwrap().into()]
|
|
|
|
} else {
|
|
|
|
tokio::net::lookup_host(host)
|
|
|
|
.await
|
|
|
|
.ok()?
|
|
|
|
.map(NamedSocketAddr::Inet)
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
};
|
|
|
|
|
2022-09-14 13:45:05 +00:00
|
|
|
if hosts.is_empty() {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
Some((pubkey, hosts))
|
|
|
|
}
|