diff --git a/Cargo.lock b/Cargo.lock index cafdba6..2717704 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -765,7 +765,7 @@ checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "jetstream" -version = "0.1.2" +version = "0.1.3" dependencies = [ "anyhow", "async-stream", @@ -804,7 +804,7 @@ dependencies = [ [[package]] name = "jetstream_p9" -version = "0.1.2" +version = "0.1.3" dependencies = [ "genfs", "jetstream_p9_wire_format_derive", @@ -816,7 +816,7 @@ dependencies = [ [[package]] name = "jetstream_p9_wire_format_derive" -version = "0.1.2" +version = "0.1.3" dependencies = [ "pretty_assertions", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index 064f162..5a06a10 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,10 @@ [package] name = "jetstream" -version = "0.1.2" +version = "0.1.3" edition = "2021" description = "Jetstream is a RPC framework for Rust, based on the 9P protocol and QUIC." license = "BSD-3-Clause" +repository = "https://github.com/sevki/jetstream" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/README.md b/README.md index 2df5d35..376f0ea 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,33 @@ -# JetStream + -JetStream is an RPC framework built on top of s2n-quic and p9. +# JetStream [![crates.io](https://img.shields.io/crates/v/jetstream.svg)](https://crates.io/crates/jetstream) [![docs.rs](https://docs.rs/jetstream/badge.svg)](https://docs.rs/jetstream) ![Build Status](https://github.com/sevki/jetstream/actions/workflows/rust.yml/badge.svg) ![Build Status](https://github.com/sevki/jetstream/actions/workflows/release.yml/badge.svg) + + +JetStream is an RPC framework built on top of s2n-quic and p9. Features: + - Bidirectional streaming - 0-RTT - mTLS - binary encoding + +## Motivation + +Building remote filesystems over internet, is the main motivation behind JetStream. + +## Ready? + +JetStream is not ready for production use. It's still in the early stages of development. + +## Alternatives + +- [grpc](https://grpc.io/) +- [capnproto](https://capnproto.org/) +- [thrift](https://thrift.apache.org/) +- [jsonrpc](https://www.jsonrpc.org/) +- [xmlrpc](http://xmlrpc.scripting.com/) + +## License + +BSD-3-Clause like the rest of the rust-p9 packages this relises on. \ No newline at end of file diff --git a/logo/JetStream.png b/logo/JetStream.png new file mode 100644 index 0000000..1e1eb24 Binary files /dev/null and b/logo/JetStream.png differ diff --git a/src/lib.rs b/src/lib.rs index a84681a..58d9870 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,7 @@ +#![doc(html_logo_url = "https://raw.githubusercontent.com/sevki/jetstream/main/logo/JetStream.png")] +#![doc(html_favicon_url = "https://raw.githubusercontent.com/sevki/jetstream/main/logo/JetStream.png")] +#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] + pub use jetstream_p9::protocol; pub mod async_wire_format; diff --git a/src/src/lib.rs b/src/src/lib.rs index d755af9..a7a7b0f 100644 --- a/src/src/lib.rs +++ b/src/src/lib.rs @@ -1,194 +1,8 @@ -use std::{ - error::Error, - io::{Read, Write}, - marker::PhantomData, - pin::Pin, - task::{Context, Poll}, -}; - -use async_wire_format::AsyncWireFormatExt; -use bytes::{BufMut, Bytes, BytesMut}; -use futures::prelude::*; -use p9::{Rframe, Rmessage, Tframe, Tmessage, WireFormat}; -use tower::Service; - pub mod async_wire_format; pub mod log; pub mod server; +pub mod service; pub use p9::protocol; -pub use p9_wire_format_derive::P9WireFormat; - -pub trait Message: WireFormat + Send + Sync {} - -/// A trait for implementing a 9P service. -/// This trait is implemented for types that can handle 9P requests. -pub trait JetStreamService: - Send + Sync + Sized -{ - fn call( - &mut self, - req: Req, - ) -> Pin< - Box< - dyn Future>> - + Send, - >, - >; -} - -/// A trait for implementing a 9P service. -/// This trait is implemented for types that can handle 9P requests. -pub trait NinePService: - JetStreamService + Send + Sync + Clone + Clone -{ -} - -/// A service that implements the 9P protocol. -#[derive(Debug, Clone, Copy)] -pub struct NinePServiceImpl { - inner: S, -} - -impl NinePServiceImpl { - pub fn new(inner: S) -> Self { - NinePServiceImpl { inner } - } -} - -impl JetStreamService for NinePServiceImpl { - fn call( - &mut self, - req: Tframe, - ) -> Pin< - Box< - dyn Future< - Output = Result< - Rframe, - Box, - >, - > + Send, - >, - > { - self.inner.call(req) - } -} - -/// A static 9p service that always returns a version message. -#[derive(Debug, Clone, Copy)] -pub struct Radar; - -#[derive(Debug, Clone, P9WireFormat)] -struct Ping(u8); - -impl Message for Ping {} - -#[derive(Debug, Clone, P9WireFormat)] -struct Pong(u8); - -impl Message for Pong {} - -impl JetStreamService for Radar { - fn call( - &mut self, - req: Ping, - ) -> Pin< - Box< - dyn Future>> - + Send, - >, - > { - Box::pin(async move { Ok(Pong(req.0)) }) - } -} - -mod ninepecho { - use super::*; - - #[derive(Debug, Clone, Copy)] - pub struct EchoService; - - impl JetStreamService for EchoService { - fn call( - &mut self, - req: Tframe, - ) -> Pin< - Box< - dyn Future< - Output = Result>, - > + Send, - >, - > { - Box::pin(async move { - Ok(Rframe { - tag: 0, - msg: Rmessage::Version(p9::Rversion { - msize: 0, - version: "9P2000".to_string(), - }), - }) - }) - } - } -} -struct Echo; - -impl Service for Echo { - type Error = Box; - type Future = Pin< - Box> + Send>, - >; - type Response = bytes::Bytes; - - fn poll_ready( - &mut self, - _cx: &mut Context<'_>, - ) -> Poll> { - Poll::Ready(Ok(())) - } - - fn call(&mut self, req: bytes::Bytes) -> Self::Future { - Box::pin(async move { Ok(req) }) - } -} - -/// A trait for converting types to and from a wire format. -pub trait ConvertWireFormat: WireFormat { - /// Converts the type to a byte representation. - /// - /// # Returns - /// - /// A `Bytes` object representing the byte representation of the type. - fn to_bytes(&self) -> Bytes; - - /// Converts a byte buffer to the type. - /// - /// # Arguments - /// - /// * `buf` - A mutable reference to a `Bytes` object containing the byte buffer. - /// - /// # Returns - /// - /// A `Result` containing the converted type or an `std::io::Error` if the conversion fails. - fn from_bytes(buf: &mut Bytes) -> Result; -} - -impl ConvertWireFormat for T { - fn to_bytes(&self) -> Bytes { - let mut buf = vec![]; - let res = self.encode(&mut buf); - if let Err(e) = res { - panic!("Failed to encode: {}", e); - } - let mut bytes = BytesMut::new(); - bytes.put_slice(buf.as_slice()); - bytes.freeze() - } - - fn from_bytes(buf: &mut Bytes) -> Result { - let buf = buf.to_vec(); - T::decode(&mut buf.as_slice()) - } -} diff --git a/src/src/service.rs b/src/src/service.rs new file mode 100644 index 0000000..2c9a3c7 --- /dev/null +++ b/src/src/service.rs @@ -0,0 +1,183 @@ +use std::{ + error::Error, + io::{Read, Write}, + marker::PhantomData, + pin::Pin, + task::{Context, Poll}, +}; + +use async_wire_format::AsyncWireFormatExt; +use bytes::{BufMut, Bytes, BytesMut}; +use futures::prelude::*; +use p9::{Rframe, Rmessage, Tframe, Tmessage, WireFormat}; +pub use p9_wire_format_derive::P9WireFormat; +use tower::Service; + +pub trait Message: WireFormat + Send + Sync {} + +/// A trait for implementing a 9P service. +/// This trait is implemented for types that can handle 9P requests. +pub trait JetStreamService: + Send + Sync + Sized +{ + fn call( + &mut self, + req: Req, + ) -> Pin< + Box< + dyn Future>> + + Send, + >, + >; +} + +/// A trait for implementing a 9P service. +/// This trait is implemented for types that can handle 9P requests. +pub trait NinePService: + JetStreamService + Send + Sync + Clone + Clone +{ +} + +/// A service that implements the 9P protocol. +#[derive(Debug, Clone, Copy)] +pub struct NinePServiceImpl { + inner: S, +} + +impl NinePServiceImpl { + pub fn new(inner: S) -> Self { + NinePServiceImpl { inner } + } +} + +impl JetStreamService for NinePServiceImpl { + fn call( + &mut self, + req: Tframe, + ) -> Pin< + Box< + dyn Future>> + + Send, + >, + > { + self.inner.call(req) + } +} + +/// A static 9p service that always returns a version message. +#[derive(Debug, Clone, Copy)] +pub struct Radar; + +#[derive(Debug, Clone, P9WireFormat)] +struct Ping(u8); + +impl Message for Ping {} + +#[derive(Debug, Clone, P9WireFormat)] +struct Pong(u8); + +impl Message for Pong {} + +impl JetStreamService for Radar { + fn call( + &mut self, + req: Ping, + ) -> Pin< + Box< + dyn Future>> + + Send, + >, + > { + Box::pin(async move { Ok(Pong(req.0)) }) + } +} + +mod ninepecho { + use super::*; + + #[derive(Debug, Clone, Copy)] + pub struct EchoService; + + impl JetStreamService for EchoService { + fn call( + &mut self, + req: Tframe, + ) -> Pin< + Box< + dyn Future< + Output = Result>, + > + Send, + >, + > { + Box::pin(async move { + Ok(Rframe { + tag: 0, + msg: Rmessage::Version(p9::Rversion { + msize: 0, + version: "9P2000".to_string(), + }), + }) + }) + } + } +} + +struct Echo; + +impl Service for Echo { + type Error = Box; + type Future = Pin< + Box> + Send>, + >; + type Response = bytes::Bytes; + + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, req: bytes::Bytes) -> Self::Future { + Box::pin(async move { Ok(req) }) + } +} + +/// A trait for converting types to and from a wire format. +pub trait ConvertWireFormat: WireFormat { + /// Converts the type to a byte representation. + /// + /// # Returns + /// + /// A `Bytes` object representing the byte representation of the type. + fn to_bytes(&self) -> Bytes; + + /// Converts a byte buffer to the type. + /// + /// # Arguments + /// + /// * `buf` - A mutable reference to a `Bytes` object containing the byte buffer. + /// + /// # Returns + /// + /// A `Result` containing the converted type or an `std::io::Error` if the conversion fails. + fn from_bytes(buf: &mut Bytes) -> Result; +} + +impl ConvertWireFormat for T { + fn to_bytes(&self) -> Bytes { + let mut buf = vec![]; + let res = self.encode(&mut buf); + if let Err(e) = res { + panic!("Failed to encode: {}", e); + } + let mut bytes = BytesMut::new(); + bytes.put_slice(buf.as_slice()); + bytes.freeze() + } + + fn from_bytes(buf: &mut Bytes) -> Result { + let buf = buf.to_vec(); + T::decode(&mut buf.as_slice()) + } +} diff --git a/third_party/p9_wire_format_derive/Cargo.toml b/third_party/p9_wire_format_derive/Cargo.toml index ae11e7c..d87ff2b 100644 --- a/third_party/p9_wire_format_derive/Cargo.toml +++ b/third_party/p9_wire_format_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "jetstream_p9_wire_format_derive" -version = "0.1.2" +version = "0.1.3" authors = ["The ChromiumOS Authors"] license = "BSD-3-Clause" description = "Supporting proc-macro for the `p9` crate." diff --git a/third_party/rust-p9/Cargo.toml b/third_party/rust-p9/Cargo.toml index 2dc7c06..35e9bb0 100644 --- a/third_party/rust-p9/Cargo.toml +++ b/third_party/rust-p9/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "jetstream_p9" -version = "0.1.2" +version = "0.1.3" authors = ["The ChromiumOS Authors"] edition = "2021" license = "BSD-3-Clause"