use std::io::{Error, ErrorKind}; use std::sync::Arc; use futures::{SinkExt, StreamExt}; use tokio::net::TcpStream; use tokio_rustls::rustls::ClientConfig; use tokio_rustls::rustls::pki_types::ServerName; use tokio_rustls::TlsConnector; use tokio_util::codec::{Framed, LengthDelimitedCodec}; use libbonknet::*; use libbonknet::servermsg::*; use libbonknet::cert::*; use uuid::Uuid; use tracing::{error, info}; async fn datastream(tlsconfig: Arc, conn_id: Uuid) -> std::io::Result<()> { let connector = TlsConnector::from(tlsconfig); let dnsname = ServerName::try_from("localhost").unwrap(); let stream = TcpStream::connect("localhost:2541").await?; let stream = connector.connect(dnsname, stream).await?; let mut transport = Framed::new(stream, LengthDelimitedCodec::new()); let msg = FromServerConnTypeMessage::OpenDataStream(conn_id); transport.send(rmp_serde::to_vec(&msg).unwrap().into()).await.unwrap(); match transport.next().await { None => panic!("None in the transport"), Some(item) => match item { Ok(buf) => { use ToPeerDataStream::*; let msg: ToPeerDataStream = rmp_serde::from_slice(&buf).unwrap(); match msg { OkDataStreamRequestAccepted => { info!("Data Stream Accepted. Waiting for Open..."); } Refused => { error!("Refused"); return Err(Error::new(ErrorKind::ConnectionRefused, "Refused")); } other => { error!("Unexpected response: {:?}", other); return Err(Error::new(ErrorKind::ConnectionRefused, "Unexpected response")); } } } Err(e) => { error!("Error: {:?}", e); return Err(e); } } } match transport.next().await { None => panic!("None in the transport"), Some(item) => match item { Ok(buf) => { use ToPeerDataStream::*; let msg: ToPeerDataStream = rmp_serde::from_slice(&buf).unwrap(); match msg { OkDataStreamOpen => { info!("Data Stream Open!. Connecting Streams."); } Revoked => { error!("Data Stream Revoked!"); return Err(Error::new(ErrorKind::ConnectionAborted, "Revoked")); } Refused => { error!("Refused"); return Err(Error::new(ErrorKind::ConnectionRefused, "Refused")); } other => { error!("Unexpected response: {:?}", other); return Err(Error::new(ErrorKind::ConnectionRefused, "Unexpected response")); } } } Err(e) => { error!("Error: {:?}", e); return Err(e); } } } // Initialize outbound stream let mut inbound = transport.into_inner(); let mut outbound = TcpStream::connect("127.0.0.1:22").await?; match tokio::io::copy_bidirectional(&mut inbound, &mut outbound).await { Ok(bytes_copied) => info!("{bytes_copied:?}"), Err(e) => error!("Error during copy: {e}"), } Ok(()) } #[tokio::main] async fn main() -> std::io::Result<()> { // Tracing Subscriber let subscriber = tracing_subscriber::FmtSubscriber::new(); tracing::subscriber::set_global_default(subscriber).unwrap(); // Server Name let my_name = "cicciopizza"; // Load Identity files let guestserver_ident = LeafCertPair::load_from_file("certs_pem/guestserver.pem").unwrap(); let broker_root = BrokerRootCerts::load_from_file("certs_pem/broker_root_ca_cert.pem").unwrap(); // Load TLS Config let guest_cert_chain = guestserver_ident.fullchain(); let tlsconfig = ClientConfig::builder() .with_root_certificates(broker_root.to_rootcertstore()) // .with_no_client_auth(); .with_client_auth_cert(guest_cert_chain, guestserver_ident.clone_key().into()) .unwrap(); let connector = TlsConnector::from(Arc::new(tlsconfig)); let dnsname = ServerName::try_from("localhost").unwrap(); let stream = TcpStream::connect("localhost:2541").await?; let stream = connector.connect(dnsname, stream).await?; let mut transport = Framed::new(stream, LengthDelimitedCodec::new()); let msg = FromGuestServerMessage::Announce { name: my_name.into() }; transport.send(rmp_serde::to_vec(&msg).unwrap().into()).await.unwrap(); // TODO: Remove this two mutable option let mut myserver_leaf: Option = None; match transport.next().await { None => { panic!("None in the transport"); } Some(item) => match item { Ok(buf) => { use libbonknet::servermsg::ToGuestServerMessage::*; let msg: ToGuestServerMessage = rmp_serde::from_slice(&buf).unwrap(); info!("{:?}", msg); match msg { OkAnnounce(payload) => { info!("Ok Announce"); myserver_leaf = Some(payload.parse()); } FailedNameAlreadyOccupied => { error!("Failed Announce, name already occupied"); return Ok(()); } } } Err(e) => { error!("Error: {:?}", e); } } } transport.close().await.unwrap(); if let Some(server_leaf) = myserver_leaf { let tlsconfig = Arc::new(ClientConfig::builder() .with_root_certificates(broker_root.to_rootcertstore()) .with_client_auth_cert(server_leaf.fullchain(), server_leaf.clone_key().into()) .unwrap()); let connector = TlsConnector::from(Arc::clone(&tlsconfig)); let dnsname = ServerName::try_from("localhost").unwrap(); let stream = TcpStream::connect("localhost:2541").await?; let stream = connector.connect(dnsname, stream).await?; let mut transport = Framed::new(stream, LengthDelimitedCodec::new()); let msg = FromServerConnTypeMessage::SendCommand; transport.send(rmp_serde::to_vec(&msg).unwrap().into()).await.unwrap(); match transport.next().await { None => { panic!("None in the transport"); } Some(item) => match item { Ok(buf) => { use libbonknet::servermsg::ToServerConnTypeReply; use libbonknet::servermsg::ToServerConnTypeReply::*; let msg: ToServerConnTypeReply = rmp_serde::from_slice(&buf).unwrap(); info!("{:?}", msg); match msg { OkSendCommand => { info!("Stream set in SendCommand mode"); } GenericFailure => { panic!("Generic Failure during SendCommand"); } others => { panic!("Unexpected Message type: {:?}", others); } } } Err(e) => { info!("Disconnection: {:?}", e); } } } // Begin WhoAmI let msg = FromServerCommandMessage::WhoAmI; transport.send(rmp_serde::to_vec(&msg).unwrap().into()).await.unwrap(); match transport.next().await { None => { panic!("None in the transport"); } Some(item) => match item { Ok(buf) => { use libbonknet::servermsg::ToServerCommandReply; use libbonknet::servermsg::ToServerCommandReply::*; let msg: ToServerCommandReply = rmp_serde::from_slice(&buf).unwrap(); info!("{:?}", msg); match msg { YouAre { name } => { info!("I am {}", name); } GenericFailure => { panic!("Generic failure during WhoAmI"); } _ => { panic!("Unexpected reply"); } } } Err(e) => { info!("Disconnection: {:?}", e); } } } transport.close().await.expect("Error during transport stream close"); // Start Subscribe Stream let connector = TlsConnector::from(Arc::clone(&tlsconfig)); let dnsname = ServerName::try_from("localhost").unwrap(); let stream = TcpStream::connect("localhost:2541").await?; let stream = connector.connect(dnsname, stream).await?; let mut transport = Framed::new(stream, LengthDelimitedCodec::new()); let msg = FromServerConnTypeMessage::Subscribe; transport.send(rmp_serde::to_vec(&msg).unwrap().into()).await.unwrap(); match transport.next().await { None => { panic!("None in the transport"); } Some(item) => match item { Ok(buf) => { use libbonknet::servermsg::ToServerConnTypeReply; use libbonknet::servermsg::ToServerConnTypeReply::*; let msg: ToServerConnTypeReply = rmp_serde::from_slice(&buf).unwrap(); info!("{:?}", msg); match msg { OkSubscribe => { info!("Stream set in Subscribe mode"); } GenericFailure => { panic!("Generic Failure during SendCommand"); } others => { panic!("Unexpected Message type: {:?}", others); } } } Err(e) => { info!("Disconnection: {:?}", e); } } } // Subscribe consume loop { match transport.next().await { None => { info!("Empty Buffer"); } Some(item) => { let mut out: Option = None; match item { Ok(buf) => { use libbonknet::servermsg::ToServerMessage; use libbonknet::servermsg::ToServerMessage::*; let msg: ToServerMessage = rmp_serde::from_slice(&buf).unwrap(); match msg { Msg { reply_id, body } => { use libbonknet::servermsg::FromServerReplyBody; use libbonknet::servermsg::ToServerMessageBody::*; match body { Request { conn_id } => { info!("I'm required with Connection ID {}", conn_id); out = Some(FromServerReply::Msg { reply_id, body: FromServerReplyBody::RequestAccepted, }); // TODO: SPAWN DATASTREAM tokio::spawn(datastream(tlsconfig.clone(), conn_id)); } } } Ping => { info!("Ping!"); out = Some(FromServerReply::Pong); } } } Err(e) => { error!("Error: {:?}", e); } } if let Some(msg) = out { transport.send(rmp_serde::to_vec(&msg).unwrap().into()).await.unwrap(); } } } } } Ok(()) }