299 lines
12 KiB
Rust
299 lines
12 KiB
Rust
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<ClientConfig>, 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<LeafCertPair> = 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<FromServerReply> = 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(())
|
|
} |