diff --git a/src/schema/api.rs b/src/schema/api.rs new file mode 100644 index 0000000..a76cb3e --- /dev/null +++ b/src/schema/api.rs @@ -0,0 +1,86 @@ +pub struct API { + inner: connection_capnp::bootstrap::Client, + log: Logger, +} + +impl Api { + fn new(log: Logger, inner: connection_capnp::bootstrap::Client) -> Self { + Self { inner} + } + pub fn from_stream(stream: TcpStream) -> (impl Future, Self) { + let network = Box::new(twoparty::VatNetwork::new(stream.clone(), stream.clone(), + rpc_twoparty_capnp::Side::Client, Default::default())); + + let mut rpc_system = RpcSystem::new(network, None); + let bffh: connection_capnp::bootstrap::Client + = rpc_system.bootstrap(rpc_twoparty_capnp::Side::Server); + + (rpc_system, Api::new(bffh)) + } + + pub async fn authentication(&mut self) -> Authentication { + let req = self.bffh.auth_request().send().promise; + // TODO: When's that an Err? + let res = req.await.unwrap(); + // TODO: When's that an Err? + let tmp = res.get().unwrap(); + Authentication::new(tmp.get_auth().unwrap()) + } + + async fn authenticate(&mut self, log: Logger) { + let r = self.bffh.auth_request(); + let auth = r.send().pipeline.get_auth(); + let m = auth.mechanisms_request().send().promise.await.unwrap(); + + for t in m.get().unwrap().get_mechs().unwrap().iter() { + info!(log, "Mechanism {} available", t.unwrap()); + } + } + + ///// Authenticate to the server. Returns true on success, false on error + //async fn authenticate(&mut self) -> Result { + // let mut sasl = SASL::new().unwrap(); + // let plain = std::ffi::CString::new("PLAIN").unwrap(); + // let mut sess = sasl.client_start(&plain).unwrap(); + // sess.set_property(rsasl::Property::GSASL_AUTHID, b"testuser"); + // sess.set_property(rsasl::Property::GSASL_PASSWORD, b"testpass"); + + // if let rsasl::Step::Done(data) = sess.step(&[]).unwrap() { + // self.send_authentication_request("PLAIN", Some(&data)).await; + // } else { + // println!("Sasl said moar data"); + // } + + // Ok(self.receive_challenge().await?) + //} + + //fn send_authentication_request(&mut self, mech: &str, init: Option<&[u8]>) -> impl Future { + // let mut outer = capnp::message::Builder::new_default(); + // let mut builder = outer.init_root::() + // .init_auth() + // .init_request(); + // builder.set_mechanism(mech); + + // if let Some(data) = init { + // builder.init_initial_response().set_initial(data); + // } + + // let stream = self.stream.clone(); + // capnp_futures::serialize::write_message(stream, outer).map(|r| r.unwrap()) + //} + + //async fn receive_challenge(&mut self) -> Result { + // let message = capnp_futures::serialize::read_message(&mut self.stream, capnp::message::ReaderOptions::default()).await.unwrap().unwrap(); + // let m = message.get_root::().unwrap(); + + // if let Ok(connection_capnp::message::Which::Auth(Ok(r))) = m.which() { + // if let Ok(auth_capnp::auth_message::Outcome(Ok(r))) = r.which() { + // if let Ok(auth_capnp::outcome::Result::Successful) = r.get_result() { + // return Ok(true); + // } + // } + // } + + // return Ok(false); + //} +} diff --git a/src/schema/authentication.rs b/src/schema/authentication.rs new file mode 100644 index 0000000..9f06007 --- /dev/null +++ b/src/schema/authentication.rs @@ -0,0 +1,52 @@ +pub struct Authentication { + inner: auth_capnp::authentication::Client, +} +impl fmt::Debug for Authentication { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Authentication") + .field("inner", &self.inner.type_id()) + .finish() + } +} + +impl Authentication { + pub fn new(inner: auth_capnp::authentication::Client) -> Self { + Self { inner } + } + + pub async fn mechanisms(&mut self) -> Vec { + let req = self.inner.mechanisms_request().send().promise; + let res = req.await.unwrap(); + let tmp = res.get().unwrap(); + tmp.get_mechs().unwrap().iter().map(|x| x.unwrap().to_string()).collect() + } +} + +async fn handshake(log: Logger, mut stream: &mut TcpStream) -> Result<(), io::Error> { + let host = "localhost"; + let program = format!("{}-{}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")); + let version = (0u32,1u32); + + let mut message = capnp::message::Builder::new_default(); + let mut builder = message.init_root::(); + + builder.set_host(host); + builder.set_major(version.0); + builder.set_minor(version.1); + builder.set_program(&program); + + capnp_futures::serialize::write_message(&mut stream, message).await.unwrap(); + if let Some(m) = capnp_futures::serialize::read_message(&mut stream, Default::default()).await.unwrap() { + let greeting = m.get_root::().unwrap(); + let peer_host = greeting.get_host().unwrap(); + let peer_program = greeting.get_program().unwrap(); + let major = greeting.get_major(); + let minor = greeting.get_minor(); + + info!(log, "Peer {} running {} API {}.{}", peer_host, peer_program, major, minor) + } else { + error!(log, "Oh noes"); + } + + Ok(()) +} diff --git a/src/schema/mod.rs b/src/schema/mod.rs index be75f82..3ebff42 100644 --- a/src/schema/mod.rs +++ b/src/schema/mod.rs @@ -1,20 +1,3 @@ -use std::fmt; -use std::any::Any; -use std::ffi::CStr; - -use slog::Logger; - -use futures::prelude::*; - -use smol::io; -use smol::net::{TcpStream, AsyncToSocketAddrs}; -use smol::LocalExecutor; -use smol::Task; - -use rsasl::SASL; - -use capnp_rpc::{twoparty, RpcSystem, rpc_twoparty_capnp}; - mod auth_capnp { include!(concat!(env!("OUT_DIR"), "/schema/auth_capnp.rs")); } @@ -25,144 +8,5 @@ mod api_capnp { include!(concat!(env!("OUT_DIR"), "/schema/api_capnp.rs")); } -const PLAIN: *const libc::c_char = b"PLAIN" as *const u8 as *const libc::c_char; - -pub struct API { - inner: connection_capnp::bootstrap::Client, - log: Logger, -} - -impl Api { - fn new(log: Logger, inner: connection_capnp::bootstrap::Client) -> Self { - Self { inner} - } - pub fn from_stream(stream: TcpStream) -> (impl Future, Self) { - let network = Box::new(twoparty::VatNetwork::new(stream.clone(), stream.clone(), - rpc_twoparty_capnp::Side::Client, Default::default())); - - let mut rpc_system = RpcSystem::new(network, None); - let bffh: connection_capnp::bootstrap::Client - = rpc_system.bootstrap(rpc_twoparty_capnp::Side::Server); - - (rpc_system, Api::new(bffh)) - } - - pub async fn authentication(&mut self) -> Authentication { - let req = self.bffh.auth_request().send().promise; - // TODO: When's that an Err? - let res = req.await.unwrap(); - // TODO: When's that an Err? - let tmp = res.get().unwrap(); - Authentication::new(tmp.get_auth().unwrap()) - } - - async fn authenticate(&mut self, log: Logger) { - let r = self.bffh.auth_request(); - let auth = r.send().pipeline.get_auth(); - let m = auth.mechanisms_request().send().promise.await.unwrap(); - - for t in m.get().unwrap().get_mechs().unwrap().iter() { - info!(log, "Mechanism {} available", t.unwrap()); - } - } - - ///// Authenticate to the server. Returns true on success, false on error - //async fn authenticate(&mut self) -> Result { - // let mut sasl = SASL::new().unwrap(); - // let plain = std::ffi::CString::new("PLAIN").unwrap(); - // let mut sess = sasl.client_start(&plain).unwrap(); - // sess.set_property(rsasl::Property::GSASL_AUTHID, b"testuser"); - // sess.set_property(rsasl::Property::GSASL_PASSWORD, b"testpass"); - - // if let rsasl::Step::Done(data) = sess.step(&[]).unwrap() { - // self.send_authentication_request("PLAIN", Some(&data)).await; - // } else { - // println!("Sasl said moar data"); - // } - - // Ok(self.receive_challenge().await?) - //} - - //fn send_authentication_request(&mut self, mech: &str, init: Option<&[u8]>) -> impl Future { - // let mut outer = capnp::message::Builder::new_default(); - // let mut builder = outer.init_root::() - // .init_auth() - // .init_request(); - // builder.set_mechanism(mech); - - // if let Some(data) = init { - // builder.init_initial_response().set_initial(data); - // } - - // let stream = self.stream.clone(); - // capnp_futures::serialize::write_message(stream, outer).map(|r| r.unwrap()) - //} - - //async fn receive_challenge(&mut self) -> Result { - // let message = capnp_futures::serialize::read_message(&mut self.stream, capnp::message::ReaderOptions::default()).await.unwrap().unwrap(); - // let m = message.get_root::().unwrap(); - - // if let Ok(connection_capnp::message::Which::Auth(Ok(r))) = m.which() { - // if let Ok(auth_capnp::auth_message::Outcome(Ok(r))) = r.which() { - // if let Ok(auth_capnp::outcome::Result::Successful) = r.get_result() { - // return Ok(true); - // } - // } - // } - - // return Ok(false); - //} -} - -pub struct Authentication { - inner: auth_capnp::authentication::Client, -} -impl fmt::Debug for Authentication { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Authentication") - .field("inner", &self.inner.type_id()) - .finish() - } -} - -impl Authentication { - pub fn new(inner: auth_capnp::authentication::Client) -> Self { - Self { inner } - } - - pub async fn mechanisms(&mut self) -> Vec { - let req = self.inner.mechanisms_request().send().promise; - let res = req.await.unwrap(); - let tmp = res.get().unwrap(); - tmp.get_mechs().unwrap().iter().map(|x| x.unwrap().to_string()).collect() - } -} - -async fn handshake(log: Logger, mut stream: &mut TcpStream) -> Result<(), io::Error> { - let host = "localhost"; - let program = format!("{}-{}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")); - let version = (0u32,1u32); - - let mut message = capnp::message::Builder::new_default(); - let mut builder = message.init_root::(); - - builder.set_host(host); - builder.set_major(version.0); - builder.set_minor(version.1); - builder.set_program(&program); - - capnp_futures::serialize::write_message(&mut stream, message).await.unwrap(); - if let Some(m) = capnp_futures::serialize::read_message(&mut stream, Default::default()).await.unwrap() { - let greeting = m.get_root::().unwrap(); - let peer_host = greeting.get_host().unwrap(); - let peer_program = greeting.get_program().unwrap(); - let major = greeting.get_major(); - let minor = greeting.get_minor(); - - info!(log, "Peer {} running {} API {}.{}", peer_host, peer_program, major, minor) - } else { - error!(log, "Oh noes"); - } - - Ok(()) -} +mod api; +mod authentication;