ftnet_utils/
utils.rs

1pub fn id52_to_public_key(id: &str) -> eyre::Result<iroh::PublicKey> {
2    use eyre::WrapErr;
3
4    let bytes = data_encoding::BASE32_DNSSEC.decode(id.as_bytes())?;
5    if bytes.len() != 32 {
6        return Err(eyre::anyhow!(
7            "read: id has invalid length: {}",
8            bytes.len()
9        ));
10    }
11
12    let bytes: [u8; 32] = bytes.try_into().unwrap(); // unwrap ok as already asserted
13
14    iroh::PublicKey::from_bytes(&bytes).wrap_err_with(|| "failed to parse id to public key")
15}
16
17pub fn public_key_to_id52(key: &iroh::PublicKey) -> String {
18    data_encoding::BASE32_DNSSEC.encode(key.as_bytes())
19}
20
21pub type FrameReader =
22    tokio_util::codec::FramedRead<iroh::endpoint::RecvStream, tokio_util::codec::LinesCodec>;
23
24pub fn frame_reader(recv: iroh::endpoint::RecvStream) -> FrameReader {
25    FrameReader::new(recv, tokio_util::codec::LinesCodec::new())
26}
27
28pub async fn get_remote_id52(conn: &iroh::endpoint::Connection) -> eyre::Result<String> {
29    let remote_node_id = match conn.remote_node_id() {
30        Ok(id) => id,
31        Err(e) => {
32            tracing::error!("could not read remote node id: {e}, closing connection");
33            // TODO: is this how we close the connection in error cases or do we send some error
34            //       and wait for other side to close the connection?
35            let e2 = conn.closed().await;
36            tracing::info!("connection closed: {e2}");
37            // TODO: send another error_code to indicate bad remote node id?
38            conn.close(0u8.into(), &[]);
39            return Err(eyre::anyhow!("could not read remote node id: {e}"));
40        }
41    };
42
43    Ok(public_key_to_id52(&remote_node_id))
44}
45
46async fn ack(send: &mut iroh::endpoint::SendStream) -> eyre::Result<()> {
47    send.write_all(format!("{}\n", ftnet_utils::ACK).as_bytes())
48        .await?;
49    Ok(())
50}
51
52pub async fn accept_bi(
53    conn: &iroh::endpoint::Connection,
54) -> eyre::Result<(
55    iroh::endpoint::SendStream,
56    FrameReader,
57    ftnet_utils::Protocol,
58)> {
59    use tokio_stream::StreamExt;
60
61    let (mut send, recv) = conn.accept_bi().await?;
62    tracing::info!("got bidirectional stream");
63    let mut recv = frame_reader(recv);
64    let msg = match recv.next().await {
65        Some(v) => v?,
66        None => {
67            tracing::error!("failed to read from incoming connection");
68            return Err(eyre::anyhow!("failed to read from incoming connection"));
69        }
70    };
71    let msg = serde_json::from_str::<ftnet_utils::Protocol>(&msg)
72        .inspect_err(|e| tracing::error!("json error for {msg}: {e}"))?;
73    ack(&mut send).await?;
74    Ok((send, recv, msg))
75}