bump to 0.1.3
This commit is contained in:
parent
466f36a1ab
commit
62f0b0f249
9 changed files with 221 additions and 195 deletions
6
Cargo.lock
generated
6
Cargo.lock
generated
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
28
README.md
28
README.md
|
@ -1,9 +1,33 @@
|
|||
# JetStream
|
||||
<img src="logo/JetStream.png" style="width: 200px">
|
||||
|
||||
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) <!--gh actions--> ![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.
|
BIN
logo/JetStream.png
Normal file
BIN
logo/JetStream.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 683 KiB |
|
@ -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;
|
||||
|
|
188
src/src/lib.rs
188
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<Req: Message, Resp: Message>:
|
||||
Send + Sync + Sized
|
||||
{
|
||||
fn call(
|
||||
&mut self,
|
||||
req: Req,
|
||||
) -> Pin<
|
||||
Box<
|
||||
dyn Future<Output = Result<Resp, Box<dyn Error + Send + Sync>>>
|
||||
+ Send,
|
||||
>,
|
||||
>;
|
||||
}
|
||||
|
||||
/// A trait for implementing a 9P service.
|
||||
/// This trait is implemented for types that can handle 9P requests.
|
||||
pub trait NinePService:
|
||||
JetStreamService<Tframe, Rframe> + Send + Sync + Clone + Clone
|
||||
{
|
||||
}
|
||||
|
||||
/// A service that implements the 9P protocol.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct NinePServiceImpl<S: NinePService> {
|
||||
inner: S,
|
||||
}
|
||||
|
||||
impl<S: NinePService> NinePServiceImpl<S> {
|
||||
pub fn new(inner: S) -> Self {
|
||||
NinePServiceImpl { inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: NinePService> JetStreamService<Tframe, Rframe> for NinePServiceImpl<S> {
|
||||
fn call(
|
||||
&mut self,
|
||||
req: Tframe,
|
||||
) -> Pin<
|
||||
Box<
|
||||
dyn Future<
|
||||
Output = Result<
|
||||
Rframe,
|
||||
Box<dyn Error + Send + Sync>,
|
||||
>,
|
||||
> + 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<Ping, Pong> for Radar {
|
||||
fn call(
|
||||
&mut self,
|
||||
req: Ping,
|
||||
) -> Pin<
|
||||
Box<
|
||||
dyn Future<Output = Result<Pong, Box<dyn Error + Send + Sync>>>
|
||||
+ Send,
|
||||
>,
|
||||
> {
|
||||
Box::pin(async move { Ok(Pong(req.0)) })
|
||||
}
|
||||
}
|
||||
|
||||
mod ninepecho {
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct EchoService;
|
||||
|
||||
impl JetStreamService<Tframe, Rframe> for EchoService {
|
||||
fn call(
|
||||
&mut self,
|
||||
req: Tframe,
|
||||
) -> Pin<
|
||||
Box<
|
||||
dyn Future<
|
||||
Output = Result<Rframe, Box<dyn Error + Send + Sync>>,
|
||||
> + Send,
|
||||
>,
|
||||
> {
|
||||
Box::pin(async move {
|
||||
Ok(Rframe {
|
||||
tag: 0,
|
||||
msg: Rmessage::Version(p9::Rversion {
|
||||
msize: 0,
|
||||
version: "9P2000".to_string(),
|
||||
}),
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct Echo;
|
||||
|
||||
impl Service<bytes::Bytes> for Echo {
|
||||
type Error = Box<dyn Error + Send + Sync>;
|
||||
type Future = Pin<
|
||||
Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>,
|
||||
>;
|
||||
type Response = bytes::Bytes;
|
||||
|
||||
fn poll_ready(
|
||||
&mut self,
|
||||
_cx: &mut Context<'_>,
|
||||
) -> Poll<Result<(), Self::Error>> {
|
||||
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<Self, std::io::Error>;
|
||||
}
|
||||
|
||||
impl<T: p9::WireFormat> 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<Self, std::io::Error> {
|
||||
let buf = buf.to_vec();
|
||||
T::decode(&mut buf.as_slice())
|
||||
}
|
||||
}
|
||||
|
|
183
src/src/service.rs
Normal file
183
src/src/service.rs
Normal file
|
@ -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<Req: Message, Resp: Message>:
|
||||
Send + Sync + Sized
|
||||
{
|
||||
fn call(
|
||||
&mut self,
|
||||
req: Req,
|
||||
) -> Pin<
|
||||
Box<
|
||||
dyn Future<Output = Result<Resp, Box<dyn Error + Send + Sync>>>
|
||||
+ Send,
|
||||
>,
|
||||
>;
|
||||
}
|
||||
|
||||
/// A trait for implementing a 9P service.
|
||||
/// This trait is implemented for types that can handle 9P requests.
|
||||
pub trait NinePService:
|
||||
JetStreamService<Tframe, Rframe> + Send + Sync + Clone + Clone
|
||||
{
|
||||
}
|
||||
|
||||
/// A service that implements the 9P protocol.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct NinePServiceImpl<S: NinePService> {
|
||||
inner: S,
|
||||
}
|
||||
|
||||
impl<S: NinePService> NinePServiceImpl<S> {
|
||||
pub fn new(inner: S) -> Self {
|
||||
NinePServiceImpl { inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: NinePService> JetStreamService<Tframe, Rframe> for NinePServiceImpl<S> {
|
||||
fn call(
|
||||
&mut self,
|
||||
req: Tframe,
|
||||
) -> Pin<
|
||||
Box<
|
||||
dyn Future<Output = Result<Rframe, Box<dyn Error + Send + Sync>>>
|
||||
+ 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<Ping, Pong> for Radar {
|
||||
fn call(
|
||||
&mut self,
|
||||
req: Ping,
|
||||
) -> Pin<
|
||||
Box<
|
||||
dyn Future<Output = Result<Pong, Box<dyn Error + Send + Sync>>>
|
||||
+ Send,
|
||||
>,
|
||||
> {
|
||||
Box::pin(async move { Ok(Pong(req.0)) })
|
||||
}
|
||||
}
|
||||
|
||||
mod ninepecho {
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct EchoService;
|
||||
|
||||
impl JetStreamService<Tframe, Rframe> for EchoService {
|
||||
fn call(
|
||||
&mut self,
|
||||
req: Tframe,
|
||||
) -> Pin<
|
||||
Box<
|
||||
dyn Future<
|
||||
Output = Result<Rframe, Box<dyn Error + Send + Sync>>,
|
||||
> + Send,
|
||||
>,
|
||||
> {
|
||||
Box::pin(async move {
|
||||
Ok(Rframe {
|
||||
tag: 0,
|
||||
msg: Rmessage::Version(p9::Rversion {
|
||||
msize: 0,
|
||||
version: "9P2000".to_string(),
|
||||
}),
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Echo;
|
||||
|
||||
impl Service<bytes::Bytes> for Echo {
|
||||
type Error = Box<dyn Error + Send + Sync>;
|
||||
type Future = Pin<
|
||||
Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>,
|
||||
>;
|
||||
type Response = bytes::Bytes;
|
||||
|
||||
fn poll_ready(
|
||||
&mut self,
|
||||
_cx: &mut Context<'_>,
|
||||
) -> Poll<Result<(), Self::Error>> {
|
||||
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<Self, std::io::Error>;
|
||||
}
|
||||
|
||||
impl<T: p9::WireFormat> 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<Self, std::io::Error> {
|
||||
let buf = buf.to_vec();
|
||||
T::decode(&mut buf.as_slice())
|
||||
}
|
||||
}
|
2
third_party/p9_wire_format_derive/Cargo.toml
vendored
2
third_party/p9_wire_format_derive/Cargo.toml
vendored
|
@ -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."
|
||||
|
|
2
third_party/rust-p9/Cargo.toml
vendored
2
third_party/rust-p9/Cargo.toml
vendored
|
@ -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"
|
||||
|
|
Loading…
Reference in a new issue