From b76b5d86c58543e05ff748117396d9c03d29a06b Mon Sep 17 00:00:00 2001 From: kuronyago Date: Wed, 8 Apr 2020 11:02:03 +0300 Subject: [PATCH 01/70] sync README with rsocket v0.5.1 --- rsocket-transport-websocket/README.md | 67 ++++++++++++++++----------- 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/rsocket-transport-websocket/README.md b/rsocket-transport-websocket/README.md index e57f9cc..ed040f4 100644 --- a/rsocket-transport-websocket/README.md +++ b/rsocket-transport-websocket/README.md @@ -6,35 +6,41 @@ Add dependencies in your `Cargo.toml`. ```toml [dependencies] -tokio = "0.2.11" -rsocket_rust = "0.5.0" - -# choose transport: -# rsocket_rust_transport_tcp = "0.5.0" -# rsocket_rust_transport_websocket = "0.5.0" +tokio = "0.2.16" +rsocket_rust = "0.5.1" +rsocket_rust_transport_websocket = "0.5.1" ``` ### Server ```rust -use rsocket_rust::prelude::*; +use log::info; +use rsocket_rust::prelude::{EchoRSocket, RSocketFactory, ServerResponder}; use rsocket_rust_transport_websocket::WebsocketServerTransport; -use std::env; use std::error::Error; #[tokio::main] async fn main() -> Result<(), Box> { + let transport: WebsocketServerTransport = WebsocketServerTransport::from("127.0.0.1:8080"); + + let responder: ServerResponder = Box::new(|setup, _socket| { + info!("accept setup: {:?}", setup); + Ok(Box::new(EchoRSocket)) + // Or you can reject setup + // Err(From::from("SETUP_NOT_ALLOW")) + }); + + let on_start: Box = + Box::new(|| info!("+++++++ echo server started! +++++++")); + RSocketFactory::receive() - .transport(WebsocketServerTransport::from("127.0.0.1:8080")) - .acceptor(|setup, _socket| { - println!("accept setup: {:?}", setup) - Ok(Box::new(EchoRSocket)) - // Or you can reject setup - // Err(From::from("SETUP_NOT_ALLOW")) - }) - .on_start(|| println!("+++++++ echo server started! +++++++")) + .transport(transport) + .acceptor(responder) + .on_start(on_start) .serve() - .await + .await?; + + Ok(()) } ``` @@ -42,27 +48,36 @@ async fn main() -> Result<(), Box> { ### Client ```rust -use rsocket_rust::prelude::*; +use log::info; +use rsocket_rust::prelude::{ClientResponder, EchoRSocket, Payload, RSocket, RSocketFactory}; use rsocket_rust_transport_websocket::WebsocketClientTransport; +use std::error::Error; #[tokio::main] -#[test] -async fn test() { - let cli = RSocketFactory::connect() - .acceptor(|| Box::new(EchoRSocket)) +async fn main() -> Result<(), Box> { + let responder: ClientResponder = Box::new(|| Box::new(EchoRSocket)); + + let client = RSocketFactory::connect() + .acceptor(responder) .transport(WebsocketClientTransport::from("127.0.0.1:8080")) .setup(Payload::from("READY!")) .mime_type("text/plain", "text/plain") .start() .await .unwrap(); - let req = Payload::builder() + + let request_payload: Payload = Payload::builder() .set_data_utf8("Hello World!") .set_metadata_utf8("Rust") .build(); - let res = cli.request_response(req).await.unwrap(); - println!("got: {:?}", res); - cli.close(); + + let res = client.request_response(request_payload).await.unwrap(); + + info!("got: {:?}", res); + + client.close(); + + Ok(()) } ``` From 6255e6fcdb763847b5205981f22954b5d29a3451 Mon Sep 17 00:00:00 2001 From: kuronyago Date: Tue, 28 Apr 2020 14:23:55 -0700 Subject: [PATCH 02/70] fire and forget: naive implementation --- rsocket-transport-wasm/src/misc.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/rsocket-transport-wasm/src/misc.rs b/rsocket-transport-wasm/src/misc.rs index 3147fc1..324790c 100644 --- a/rsocket-transport-wasm/src/misc.rs +++ b/rsocket-transport-wasm/src/misc.rs @@ -2,7 +2,7 @@ use super::client::WebsocketClientTransport; use super::runtime::WASMSpawner; use js_sys::{Promise, Uint8Array}; use rsocket_rust::prelude::*; -use wasm_bindgen::prelude::*; +use wasm_bindgen::prelude::{wasm_bindgen, JsValue}; use wasm_bindgen_futures::future_to_promise; #[derive(Serialize, Deserialize)] @@ -81,6 +81,16 @@ impl JsClient { } }) } + + pub fn fire_and_forget(&self, request: &JsValue) -> Promise { + let inner = self.inner.clone(); + let request: JsPayload = request.into_serde().unwrap(); + + future_to_promise(async move { + inner.fire_and_forget(request.into()); + Ok(JsValue::NULL) + }) + } } #[inline] From 5c8a8eed6e54f98fc90042008b63d35b493fbe8f Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Sun, 12 Apr 2020 20:47:17 +0800 Subject: [PATCH 03/70] New feature: messaging. --- Cargo.toml | 7 +- examples/Cargo.toml | 2 +- rsocket-messaging/Cargo.toml | 18 ++ rsocket-messaging/src/lib.rs | 7 + rsocket-messaging/src/misc.rs | 38 +++ rsocket-messaging/src/requester.rs | 118 +++++++ rsocket-test/Cargo.toml | 7 +- rsocket-test/tests/test_composite_metadata.rs | 19 +- rsocket-test/tests/test_messaging.rs | 52 +++ rsocket-test/tests/test_mimes.rs | 15 +- rsocket-transport-tcp/Cargo.toml | 4 +- rsocket-transport-tcp/src/codec.rs | 3 +- rsocket-transport-wasm/src/misc.rs | 2 +- rsocket-transport-websocket/Cargo.toml | 2 +- rsocket/Cargo.toml | 2 +- rsocket/src/extension/composite.rs | 133 ++++---- rsocket/src/extension/mime.rs | 305 ++++++++++++++++++ rsocket/src/extension/mod.rs | 4 +- rsocket/src/extension/routing.rs | 1 - rsocket/src/frame/error.rs | 17 +- rsocket/src/frame/keepalive.rs | 9 +- rsocket/src/frame/lease.rs | 9 +- rsocket/src/frame/metadata_push.rs | 9 +- rsocket/src/frame/mod.rs | 4 - rsocket/src/frame/payload.rs | 16 +- rsocket/src/frame/request_channel.rs | 16 +- rsocket/src/frame/request_fnf.rs | 16 +- rsocket/src/frame/request_n.rs | 2 +- rsocket/src/frame/request_response.rs | 16 +- rsocket/src/frame/request_stream.rs | 16 +- rsocket/src/frame/resume.rs | 2 +- rsocket/src/frame/resume_ok.rs | 2 +- rsocket/src/frame/setup.rs | 121 ++++--- rsocket/src/frame/utils.rs | 10 +- rsocket/src/lib.rs | 1 - rsocket/src/mime.rs | 256 --------------- rsocket/src/payload/normal.rs | 32 +- rsocket/src/payload/setup.rs | 32 +- rsocket/src/transport/fragmentation.rs | 4 - rsocket/src/transport/socket.rs | 54 +++- 40 files changed, 892 insertions(+), 491 deletions(-) create mode 100644 rsocket-messaging/Cargo.toml create mode 100644 rsocket-messaging/src/lib.rs create mode 100644 rsocket-messaging/src/misc.rs create mode 100644 rsocket-messaging/src/requester.rs create mode 100644 rsocket-test/tests/test_messaging.rs create mode 100644 rsocket/src/extension/mime.rs delete mode 100644 rsocket/src/mime.rs diff --git a/Cargo.toml b/Cargo.toml index 064b121..97b5c80 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,15 @@ [workspace] members = [ +# core "rsocket", +# transports "rsocket-transport-tcp", "rsocket-transport-websocket", "rsocket-transport-wasm", - -# Internal +# extra +"rsocket-messaging", +# internal "examples", "rsocket-test", ] diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 1e6130e..390b270 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -21,7 +21,7 @@ path = "../rsocket-transport-tcp" path = "../rsocket-transport-websocket" [dev-dependencies.tokio] -version = "0.2.16" +version = "0.2.19" default-features = false features = ["full"] diff --git a/rsocket-messaging/Cargo.toml b/rsocket-messaging/Cargo.toml new file mode 100644 index 0000000..8782ca6 --- /dev/null +++ b/rsocket-messaging/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "rsocket_rust_messaging" +version = "0.1.0" +authors = ["Jeffsky "] +edition = "2018" + +[dependencies] +log = "0.4.8" +futures = "0.3.4" +bytes = "0.5.4" +serde = "1.0.106" +serde_json = "1.0.52" +serde_cbor = "0.11.1" +hex = "0.4.2" + +[dependencies.rsocket_rust] +path = "../rsocket" +features = ["frame"] \ No newline at end of file diff --git a/rsocket-messaging/src/lib.rs b/rsocket-messaging/src/lib.rs new file mode 100644 index 0000000..689dff2 --- /dev/null +++ b/rsocket-messaging/src/lib.rs @@ -0,0 +1,7 @@ +#[macro_use] +extern crate log; + +mod misc; +mod requester; + +pub use requester::{RequestSpec, Requester}; diff --git a/rsocket-messaging/src/misc.rs b/rsocket-messaging/src/misc.rs new file mode 100644 index 0000000..a8e2bd5 --- /dev/null +++ b/rsocket-messaging/src/misc.rs @@ -0,0 +1,38 @@ +use bytes::{BufMut, BytesMut}; +use rsocket_rust::extension::{MimeType, MIME_APPLICATION_CBOR, MIME_APPLICATION_JSON}; +use serde::{Deserialize, Serialize}; +use std::error::Error; + +pub(crate) fn unmarshal<'a, T>(mime_type: &MimeType, raw: &'a [u8]) -> Result> +where + T: Deserialize<'a>, +{ + match *mime_type { + MIME_APPLICATION_JSON => Ok(serde_json::from_slice(raw)?), + MIME_APPLICATION_CBOR => Ok(serde_cbor::from_slice(raw)?), + _ => panic!(""), + } +} + +pub(crate) fn marshal( + mime_type: &MimeType, + bf: &mut BytesMut, + data: &T, +) -> Result<(), Box> +where + T: Sized + Serialize, +{ + match *mime_type { + MIME_APPLICATION_JSON => { + let raw = serde_json::to_vec(data)?; + bf.put_slice(&raw[..]); + Ok(()) + } + MIME_APPLICATION_CBOR => { + let raw = serde_cbor::to_vec(data)?; + bf.put_slice(&raw[..]); + Ok(()) + } + _ => panic!(""), + } +} diff --git a/rsocket-messaging/src/requester.rs b/rsocket-messaging/src/requester.rs new file mode 100644 index 0000000..5218a3b --- /dev/null +++ b/rsocket-messaging/src/requester.rs @@ -0,0 +1,118 @@ +use super::misc::{marshal, unmarshal}; +use bytes::{BufMut, BytesMut}; +use rsocket_rust::error::RSocketError; +use rsocket_rust::extension::{ + CompositeMetadata, MimeType, RoutingMetadata, MIME_APPLICATION_JSON, + MIME_MESSAGE_X_RSOCKET_ROUTING_V0, +}; +use rsocket_rust::prelude::*; +use rsocket_rust::utils::Writeable; +use serde::{Deserialize, Serialize}; +use std::collections::LinkedList; +use std::error::Error; + +pub struct Requester +where + S: RSocket + Clone, +{ + rsocket: S, +} + +pub struct RequestSpec +where + S: RSocket + Clone, +{ + data_buf: BytesMut, + rsocket: S, + data_mime_type: MimeType, + metadatas: LinkedList<(MimeType, Vec)>, +} + +impl Requester +where + C: RSocket + Clone, +{ + pub fn new(rsocket: C) -> Requester { + Requester { rsocket } + } + + pub fn route(&self, route: &str) -> RequestSpec { + let routing = RoutingMetadata::builder().push_str(route).build(); + let mut buf = BytesMut::new(); + routing.write_to(&mut buf); + + let mut metadatas: LinkedList<(MimeType, Vec)> = Default::default(); + metadatas.push_back((MIME_MESSAGE_X_RSOCKET_ROUTING_V0, buf.to_vec())); + RequestSpec { + data_buf: BytesMut::new(), + rsocket: self.rsocket.clone(), + data_mime_type: MIME_APPLICATION_JSON, + metadatas, + } + } +} + +impl RequestSpec +where + C: RSocket + Clone, +{ + pub fn metadata(&mut self, metadata: &T, mime_type: &str) -> Result<(), Box> + where + T: Sized + Serialize, + { + let mime_type = MimeType::from(mime_type); + let mut b = BytesMut::new(); + marshal(&mime_type, &mut b, metadata)?; + self.metadatas.push_back((mime_type, b.to_vec())); + Ok(()) + } + + pub fn data(&mut self, data: &T) -> Result<(), Box> + where + T: Sized + Serialize, + { + marshal(&self.data_mime_type, &mut self.data_buf, data) + } + + pub async fn retrieve_mono(&self) -> Unpacker { + let req = self.to_req(); + let res = self.rsocket.request_response(req).await; + Unpacker { + mime_type: self.data_mime_type.clone(), + inner: res, + } + } + + fn to_req(&self) -> Payload { + let mut b = BytesMut::new(); + let mut c = CompositeMetadata::builder(); + for (a, b) in self.metadatas.iter() { + c = c.push(a.clone(), b); + } + c.build().write_to(&mut b); + Payload::builder() + .set_metadata(b.to_vec()) + .set_data(self.data_buf.to_vec()) + .build() + } +} + +pub struct Unpacker { + mime_type: MimeType, + inner: Result, +} + +impl Unpacker { + pub fn block<'a, T>(&'a self) -> Result, Box> + where + T: Deserialize<'a>, + { + match &self.inner { + Ok(inner) => match inner.data() { + Some(raw) => Ok(Some(unmarshal(&self.mime_type, &raw.as_ref())?)), + None => Ok(None), + }, + Err(e) => Err(format!("{}", e).into()), + } + } +} diff --git a/rsocket-test/Cargo.toml b/rsocket-test/Cargo.toml index 3864908..1023dcf 100644 --- a/rsocket-test/Cargo.toml +++ b/rsocket-test/Cargo.toml @@ -12,6 +12,8 @@ env_logger = "0.7.1" bytes = "0.5.4" hex = "0.4.2" rand = "0.7.3" +serde = "1.0.106" +serde_derive = "1.0.106" [dev-dependencies.rsocket_rust] path = "../rsocket" @@ -23,7 +25,10 @@ path = "../rsocket-transport-tcp" [dev-dependencies.rsocket_rust_transport_websocket] path = "../rsocket-transport-websocket" +[dev-dependencies.rsocket_rust_messaging] +path = "../rsocket-messaging" + [dev-dependencies.tokio] -version = "0.2.16" +version = "0.2.20" default-features = false features = ["full"] diff --git a/rsocket-test/tests/test_composite_metadata.rs b/rsocket-test/tests/test_composite_metadata.rs index 37a34cd..d7ef7df 100644 --- a/rsocket-test/tests/test_composite_metadata.rs +++ b/rsocket-test/tests/test_composite_metadata.rs @@ -1,20 +1,23 @@ use bytes::BytesMut; -use rsocket_rust::extension::{CompositeMetadata, Metadata}; +use rsocket_rust::extension::{self, CompositeMetadata, CompositeMetadataEntry, MimeType}; use rsocket_rust::utils::Writeable; #[test] fn encode_and_decode_composite_metadata() { - let bingo = |metadatas: Vec<&Metadata>| { + let bingo = |metadatas: Vec<&CompositeMetadataEntry>| { assert_eq!(2, metadatas.len()); - assert_eq!("text/plain", metadatas[0].get_mime()); - assert_eq!(b"Hello World!", metadatas[0].get_payload().as_ref()); - assert_eq!("application/not_well", metadatas[1].get_mime()); - assert_eq!(b"Not Well!", metadatas[1].get_payload().as_ref()); + assert_eq!(extension::MIME_TEXT_PLAIN, *metadatas[0].get_mime_type()); + assert_eq!("Hello World!", metadatas[0].get_metadata_utf8()); + assert_eq!( + MimeType::from("application/not_well"), + *metadatas[1].get_mime_type() + ); + assert_eq!(b"Not Well!", metadatas[1].get_metadata().as_ref()); }; let cm = CompositeMetadata::builder() - .push("text/plain", b"Hello World!") - .push("application/not_well", "Not Well!") + .push(MimeType::from("text/plain"), b"Hello World!") + .push(MimeType::from("application/not_well"), "Not Well!") .build(); bingo(cm.iter().collect()); diff --git a/rsocket-test/tests/test_messaging.rs b/rsocket-test/tests/test_messaging.rs new file mode 100644 index 0000000..23e9fc2 --- /dev/null +++ b/rsocket-test/tests/test_messaging.rs @@ -0,0 +1,52 @@ +#[macro_use] +extern crate log; +#[macro_use] +extern crate serde_derive; + +use rsocket_rust::prelude::*; +use rsocket_rust_messaging::*; +use rsocket_rust_transport_tcp::TcpClientTransport; + +#[derive(Serialize, Deserialize, Debug)] +pub struct Student { + id: i64, + name: String, + birth: String, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct Response { + code: i32, + message: Option, + data: T, +} + +#[tokio::main] +#[test] +#[ignore] +async fn test_messaging() { + let rsocket = RSocketFactory::connect() + .transport(TcpClientTransport::from("tcp://127.0.0.1:7878")) + .data_mime_type("application/json") + .metadata_mime_type("message/x.rsocket.composite-metadata.v0") + .start() + .await + .expect("Connect failed!"); + let requester = Requester::new(rsocket); + + let post = Student { + id: 1234, + name: "Jeffsky".to_owned(), + birth: "2020-01-01".to_owned(), + }; + let mut req = requester.route("student.v1.upsert"); + req.data(&post).unwrap(); + let res: Response = req + .retrieve_mono() + .await + .block() + .expect("Retrieve failed!") + .expect("Empty result!"); + println!("------> RESPONSE: {:?}", res); + () +} diff --git a/rsocket-test/tests/test_mimes.rs b/rsocket-test/tests/test_mimes.rs index 9c86e33..f52509a 100644 --- a/rsocket-test/tests/test_mimes.rs +++ b/rsocket-test/tests/test_mimes.rs @@ -1,15 +1,12 @@ extern crate rsocket_rust; -use rsocket_rust::mime::WellKnownMIME; +use rsocket_rust::extension::{self, MimeType}; #[test] fn test_wellknown() { - let got = WellKnownMIME::from("application/json"); - assert_eq!(WellKnownMIME::ApplicationJson, got); - WellKnownMIME::foreach(|m| { - let mut result = WellKnownMIME::from(m.raw()); - assert_eq!(m, &result); - result = WellKnownMIME::from(format!("{}", m)); - assert_eq!(m, &result); - }); + let well = MimeType::from("application/json"); + assert_eq!(extension::MIME_APPLICATION_JSON, well); + assert_eq!(0x05, well.as_u8().unwrap()); + let custom = MimeType::from("application/custom"); + assert_eq!(MimeType::Normal("application/custom".to_owned()), custom); } diff --git a/rsocket-transport-tcp/Cargo.toml b/rsocket-transport-tcp/Cargo.toml index c35fa65..2c93762 100644 --- a/rsocket-transport-tcp/Cargo.toml +++ b/rsocket-transport-tcp/Cargo.toml @@ -19,12 +19,12 @@ path = "../rsocket" features = ["frame"] [dependencies.tokio] -version = "0.2.16" +version = "0.2.20" default-features = false features = [ "rt-core", "rt-threaded", "tcp", "sync", "stream" ] [dependencies.tokio-util] -version = "0.2.0" +version = "0.3.1" default-features = false features = ["codec"] diff --git a/rsocket-transport-tcp/src/codec.rs b/rsocket-transport-tcp/src/codec.rs index eefc046..c240bd6 100644 --- a/rsocket-transport-tcp/src/codec.rs +++ b/rsocket-transport-tcp/src/codec.rs @@ -28,8 +28,7 @@ impl Decoder for LengthBasedFrameCodec { } } -impl Encoder for LengthBasedFrameCodec { - type Item = Frame; +impl Encoder for LengthBasedFrameCodec { type Error = Error; fn encode(&mut self, item: Frame, buf: &mut BytesMut) -> Result<(), Self::Error> { let l = item.len(); diff --git a/rsocket-transport-wasm/src/misc.rs b/rsocket-transport-wasm/src/misc.rs index 324790c..38fbfda 100644 --- a/rsocket-transport-wasm/src/misc.rs +++ b/rsocket-transport-wasm/src/misc.rs @@ -87,7 +87,7 @@ impl JsClient { let request: JsPayload = request.into_serde().unwrap(); future_to_promise(async move { - inner.fire_and_forget(request.into()); + inner.fire_and_forget(request.into()).await; Ok(JsValue::NULL) }) } diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index 939a56d..6af15e7 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -21,6 +21,6 @@ path = "../rsocket" features = ["frame"] [dependencies.tokio] -version = "0.2.16" +version = "0.2.19" default-features = false features = [ "rt-core", "rt-threaded", "tcp", "sync", "stream" ] diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index c82e953..76e6ae8 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -16,7 +16,7 @@ futures = "0.3.4" lazy_static = "1.4.0" [dependencies.tokio] -version = "0.2.16" +version = "0.2.19" default-features = false features = [ "rt-core", "rt-threaded", "sync", "stream" ] diff --git a/rsocket/src/extension/composite.rs b/rsocket/src/extension/composite.rs index 71418f7..1984127 100644 --- a/rsocket/src/extension/composite.rs +++ b/rsocket/src/extension/composite.rs @@ -1,21 +1,22 @@ +use super::mime::MimeType; use crate::error::{ErrorKind, RSocketError}; -use crate::mime::WellKnownMIME; use crate::utils::{RSocketResult, Writeable, U24}; use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::collections::LinkedList; +use std::convert::TryFrom; use std::result::Result; -const MAX_MIME_LEN: usize = 0x7F; +const MAX_MIME_LEN: usize = 0x7F + 1; #[derive(Debug, Clone, Eq, PartialEq, Default)] pub struct CompositeMetadata { - metadatas: LinkedList, + metadatas: LinkedList, } #[derive(Debug, Clone, Eq, PartialEq)] -pub struct Metadata { - mime: String, - payload: Bytes, +pub struct CompositeMetadataEntry { + mime_type: MimeType, + metadata: Bytes, } pub struct CompositeMetadataBuilder { @@ -23,19 +24,18 @@ pub struct CompositeMetadataBuilder { } impl CompositeMetadataBuilder { - pub fn push(mut self, mime: I, payload: A) -> Self + pub fn push(mut self, mime_type: MimeType, payload: A) -> Self where - I: Into, A: AsRef<[u8]>, { let mut bf = BytesMut::new(); bf.put_slice(payload.as_ref()); - let m = Metadata::new(mime.into(), bf.freeze()); + let m = CompositeMetadataEntry::new(mime_type, bf.freeze()); self.inner.push(m); self } - pub fn push_metadata(mut self, metadata: Metadata) -> Self { + pub fn push_entry(mut self, metadata: CompositeMetadataEntry) -> Self { self.inner.push(metadata); self } @@ -96,103 +96,122 @@ impl CompositeMetadata { let mut metadatas = LinkedList::new(); loop { match Self::decode_once(b) { - Ok(op) => match op { - Some(v) => metadatas.push_back(v), - None => break, - }, + Ok(Some(v)) => metadatas.push_back(v), + Ok(None) => break, Err(e) => return Err(e), } } Ok(CompositeMetadata { metadatas }) } - pub fn iter(&self) -> impl Iterator { + pub fn iter(&self) -> impl Iterator { self.metadatas.iter() } #[inline] - fn decode_once(bs: &mut BytesMut) -> RSocketResult> { + fn decode_once(bs: &mut BytesMut) -> RSocketResult> { if bs.is_empty() { return Ok(None); } let first: u8 = bs.get_u8(); - let m = if 0x80 & first != 0 { + let mime_type = if 0x80 & first != 0 { // Well - let well = WellKnownMIME::from(first & 0x7F); - well.str().to_string() + let n = first & 0x7F; + match MimeType::parse(n) { + Some(well) => well, + None => { + let err_str = format!("invalid Well-Known MIME type: identifier={:x}", n); + return Err(RSocketError::from(err_str)); + } + } } else { // Bad - let mime_len = first as usize; + let mime_len = (first as usize) + 1; if bs.len() < mime_len { - return Err(RSocketError::from("broken COMPOSITE_METADATA bytes!")); + return Err(RSocketError::from( + "broken composite metadata: empty MIME type!", + )); } let front = bs.split_to(mime_len); - String::from_utf8(front.to_vec()).unwrap() + MimeType::Normal(String::from_utf8(front.to_vec()).unwrap()) }; if bs.len() < 3 { - return Err(RSocketError::from("broken COMPOSITE_METADATA bytes!")); + return Err(RSocketError::from( + "broken composite metadata: not enough bytes!", + )); } let payload_size = U24::read_advance(bs) as usize; if bs.len() < payload_size { - return Err(RSocketError::from("broken COMPOSITE_METADATA bytes!")); + return Err(RSocketError::from(format!( + "broken composite metadata: require {} bytes!", + payload_size + ))); } - let p = bs.split_to(payload_size).freeze(); - Ok(Some(Metadata::new(m, p))) + let metadata = bs.split_to(payload_size).freeze(); + Ok(Some(CompositeMetadataEntry::new(mime_type, metadata))) } - pub fn push(&mut self, metadata: Metadata) { + pub fn push(&mut self, metadata: CompositeMetadataEntry) { self.metadatas.push_back(metadata) } } -impl Metadata { - pub fn new(mime: String, payload: Bytes) -> Metadata { - if mime.len() > MAX_MIME_LEN { - panic!("too large MIME type!"); - } - if payload.len() > U24::max() { +impl CompositeMetadataEntry { + pub fn new(mime_type: MimeType, metadata: Bytes) -> CompositeMetadataEntry { + if metadata.len() > U24::max() { panic!("too large Payload!") } - Metadata { mime, payload } + CompositeMetadataEntry { + mime_type: mime_type, + metadata: metadata, + } + } + + pub fn get_mime_type(&self) -> &MimeType { + &self.mime_type } - pub fn get_mime(&self) -> &String { - &self.mime + pub fn get_metadata(&self) -> &Bytes { + &self.metadata } - pub fn get_payload(&self) -> &Bytes { - &self.payload + pub fn get_metadata_utf8(&self) -> &str { + std::str::from_utf8(self.metadata.as_ref()).expect("Invalid UTF-8 bytes.") } } -impl Writeable for Metadata { +impl Writeable for CompositeMetadataEntry { fn write_to(&self, bf: &mut BytesMut) { - let mi = WellKnownMIME::from(self.mime.as_str()); - let first_byte: u8 = if mi == WellKnownMIME::Unknown { - // Bad - self.mime.len() as u8 - } else { - // Goodmi - 0x80 | mi.raw() + match &self.mime_type { + MimeType::WellKnown(n) => { + // WellKnown + bf.put_u8(0x80 | n); + } + MimeType::Normal(s) => { + // NotWellKnown + let mime_type_len = s.len() as u8; + if mime_type_len == 0 { + panic!("invalid length of MimeType!") + } + bf.put_u8(mime_type_len - 1); + bf.put_slice(s.as_ref()); + } }; - let payload_size = self.payload.len(); - - bf.put_u8(first_byte); - if first_byte & 0x80 == 0 { - bf.put_slice(self.mime.as_bytes()); + let metadata_len = self.metadata.len() as u32; + U24::write(metadata_len, bf); + if metadata_len > 0 { + bf.put(self.metadata.bytes()); } - U24::write(payload_size as u32, bf); - bf.put(self.payload.bytes()); } fn len(&self) -> usize { + // 1byte(MIME) + 3bytes(length of payload in u24) let mut amount = 4; - let wellknown = WellKnownMIME::from(self.mime.as_str()) != WellKnownMIME::Unknown; - if wellknown { - amount += self.mime.len(); + if let MimeType::Normal(s) = &self.mime_type { + amount += s.len(); } - amount += self.payload.len(); + amount += self.metadata.len(); amount } } diff --git a/rsocket/src/extension/mime.rs b/rsocket/src/extension/mime.rs new file mode 100644 index 0000000..2f6ccca --- /dev/null +++ b/rsocket/src/extension/mime.rs @@ -0,0 +1,305 @@ +use std::collections::HashMap; +use std::error::Error; +use std::fmt; + +#[derive(PartialEq, Eq, Debug, Clone, Hash)] +pub enum MimeType { + Normal(String), + WellKnown(u8), +} + +lazy_static! { + static ref U8_TO_STR: HashMap = { + let mut m = HashMap::new(); + for it in list_all().iter() { + m.insert(it.0, it.1); + } + m + }; +} + +lazy_static! { + static ref STR_TO_U8: HashMap<&'static str, u8> = { + let mut m = HashMap::new(); + for it in list_all().iter() { + m.insert(it.1, it.0); + } + m + }; +} + +impl MimeType { + pub fn parse(value: u8) -> Option { + U8_TO_STR.get(&value).map(|it| Self::WellKnown(value)) + } + + pub fn as_u8(&self) -> Option { + match self { + Self::WellKnown(n) => Some(n.clone()), + Self::Normal(_) => None, + } + } +} + +impl Into for MimeType { + fn into(self) -> String { + self.as_ref().to_owned() + } +} + +impl AsRef for MimeType { + fn as_ref(&self) -> &str { + match self { + Self::Normal(s) => &s, + Self::WellKnown(n) => U8_TO_STR.get(n).unwrap(), + } + } +} + +impl From<&str> for MimeType { + fn from(value: &str) -> MimeType { + match STR_TO_U8.get(&value) { + Some(v) => Self::WellKnown(v.clone()), + None => Self::Normal(value.to_owned()), + } + } +} + +impl fmt::Display for MimeType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Normal(s) => write!(f, "{}", s), + Self::WellKnown(n) => match U8_TO_STR.get(n) { + Some(v) => write!(f, "{}", v), + None => Err(fmt::Error), + }, + } + } +} + +macro_rules! mime { + ($name:ident,$mime_name:ident, $n:expr,$s:expr) => { + const $name: (u8, &str) = ($n, $s); + pub const $mime_name: MimeType = MimeType::WellKnown($n); + }; +} + +mime!( + APPLICATION_AVRO, + MIME_APPLICATION_AVRO, + 0x00, + "application/avro" +); +mime!( + APPLICATION_CBOR, + MIME_APPLICATION_CBOR, + 0x01, + "application/avro" +); +mime!( + APPLICATION_GRAPHQL, + MIME_APPLICATION_GRAPHQL, + 0x02, + "application/graphql" +); +mime!( + APPLICATION_GZIP, + MIME_APPLICATION_GZIP, + 0x03, + "application/gzip" +); +mime!( + APPLICATION_JAVASCRIPT, + MIME_APPLICATION_JAVASCRIPT, + 0x04, + "application/javascript" +); +mime!( + APPLICATION_JSON, + MIME_APPLICATION_JSON, + 0x05, + "application/json" +); +mime!( + APPLICATION_OCTET_STREAM, + MIME_APPLICATION_OCTET_STREAM, + 0x06, + "application/octet-stream" +); +mime!( + APPLICATION_PDF, + MIME_APPLICATION_PDF, + 0x07, + "application/pdf" +); +mime!( + APPLICATION_VND_APACHE_THRIFT_BINARY, + MIME_APPLICATION_VND_APACHE_THRIFT_BINARY, + 0x08, + "application/vnd.apache.thrift.binary" +); +mime!( + APPLICATION_VND_GOOGLE_PROTOBUF, + MIME_APPLICATION_VND_GOOGLE_PROTOBUF, + 0x09, + "application/vnd.google.protobuf" +); +mime!( + APPLICATION_XML, + MIME_APPLICATION_XML, + 0x0A, + "application/xml" +); +mime!( + APPLICATION_ZIP, + MIME_APPLICATION_ZIP, + 0x0B, + "application/zip" +); +mime!(AUDIO_AAC, MIME_AUDIO_AAC, 0x0C, "audio/aac"); +mime!(AUDIO_MP3, MIME_AUDIO_MP3, 0x0D, "audio/mp3"); +mime!(AUDIO_MP4, MIME_AUDIO_MP4, 0x0E, "audio/mp4"); +mime!(AUDIO_MPEG3, MIME_AUDIO_MPEG3, 0x0F, "audio/mpeg3"); +mime!(AUDIO_MPEG, MIME_AUDIO_MPEG, 0x10, "audio/mpeg"); +mime!(AUDIO_OGG, MIME_AUDIO_OGG, 0x11, "audio/ogg"); +mime!(AUDIO_OPUS, MIME_AUDIO_OPUS, 0x12, "audio/opus"); +mime!(AUDIO_VORBIS, MIME_AUDIO_VORBIS, 0x13, "audio/vorbis"); +mime!(IMAGE_BMP, MIME_IMAGE_BMP, 0x14, "image/bmp"); +mime!(IMAGE_GIF, MIME_IMAGE_GIF, 0x15, "image/gif"); +mime!( + IMAGE_HEIC_SEQUENCE, + MIME_IMAGE_HEIC_SEQUENCE, + 0x16, + "image/heic-sequence" +); +mime!(IMAGE_HEIC, MIME_IMAGE_HEIC, 0x17, "image/heic"); +mime!( + IMAGE_HEIF_SEQUENCE, + MIME_IMAGE_HEIF_SEQUENCE, + 0x18, + "image/heif-sequence" +); +mime!(IMAGE_HEIF, MIME_IMAGE_HEIF, 0x19, "image/heif"); +mime!(IMAGE_JPEG, MIME_IMAGE_JPEG, 0x1A, "image/jpeg"); +mime!(IMAGE_PNG, MIME_IMAGE_PNG, 0x1B, "image/png"); +mime!(IMAGE_TIFF, MIME_IMAGE_TIFF, 0x1C, "image/tiff"); +mime!( + MULTIPART_MIXED, + MIME_MULTIPART_MIXED, + 0x1D, + "multipart/mixed" +); +mime!(TEXT_CSS, MIME_TEXT_CSS, 0x1E, "text/css"); +mime!(TEXT_CSV, MIME_TEXT_CSV, 0x1F, "text/csv"); +mime!(TEXT_HTML, MIME_TEXT_HTML, 0x20, "text/html"); +mime!(TEXT_PLAIN, MIME_TEXT_PLAIN, 0x21, "text/plain"); +mime!(TEXT_XML, MIME_TEXT_XML, 0x22, "text/xml"); +mime!(VIDEO_H264, MIME_VIDEO_H264, 0x23, "video/H264"); +mime!(VIDEO_H265, MIME_VIDEO_H265, 0x24, "video/H265"); +mime!(VIDEO_VP8, MIME_VIDEO_VP8, 0x25, "video/VP8"); +mime!( + APPLICATION_X_HESSIAN, + MIME_APPLICATION_X_HESSIAN, + 0x26, + "application/x-hessian" +); +mime!( + APPLICATION_X_JAVA_OBJECT, + MIME_APPLICATION_X_JAVA_OBJECT, + 0x27, + "application/x-java-object" +); +mime!( + APPLICATION_CLOUDEVENTS_JSON, + MIME_APPLICATION_CLOUDEVENTS_JSON, + 0x28, + "application/cloudevents+json" +); +mime!( + MESSAGE_X_RSOCKET_MIME_TYPE_V0, + MIME_MESSAGE_X_RSOCKET_MIME_TYPE_V0, + 0x7A, + "message/x.rsocket.mime-type.v0" +); +mime!( + MESSAGE_X_RSOCKET_ACCEPT_TIME_TYPES_V0, + MIME_MESSAGE_X_RSOCKET_ACCEPT_TIME_TYPES_V0, + 0x7B, + "message/x.rsocket.accept-mime-types.v0" +); +mime!( + MESSAGE_X_RSOCKET_AUTHENTICATION_V0, + MIME_MESSAGE_X_RSOCKET_AUTHENTICATION_V0, + 0x7C, + "message/x.rsocket.authentication.v0" +); +mime!( + MESSAGE_X_RSOCKET_TRACING_ZIPKIN_V0, + MIME_MESSAGE_X_RSOCKET_TRACING_ZIPKIN_V0, + 0x7D, + "message/x.rsocket.tracing-zipkin.v0" +); +mime!( + MESSAGE_X_RSOCKET_ROUTING_V0, + MIME_MESSAGE_X_RSOCKET_ROUTING_V0, + 0x7E, + "message/x.rsocket.routing.v0" +); +mime!( + MESSAGE_X_RSOCKET_COMPOSITE_METADATA_V0, + MIME_MESSAGE_X_RSOCKET_COMPOSITE_METADATA_V0, + 0x7F, + "message/x.rsocket.composite-metadata.v0" +); + +fn list_all() -> Vec<(u8, &'static str)> { + vec![ + APPLICATION_AVRO, + APPLICATION_CBOR, + APPLICATION_GRAPHQL, + APPLICATION_GZIP, + APPLICATION_JAVASCRIPT, + APPLICATION_JSON, + APPLICATION_OCTET_STREAM, + APPLICATION_PDF, + APPLICATION_VND_APACHE_THRIFT_BINARY, + APPLICATION_VND_GOOGLE_PROTOBUF, + APPLICATION_XML, + APPLICATION_ZIP, + AUDIO_AAC, + AUDIO_MP3, + AUDIO_MP4, + AUDIO_MPEG3, + AUDIO_MPEG, + AUDIO_OGG, + AUDIO_OPUS, + AUDIO_VORBIS, + IMAGE_BMP, + IMAGE_GIF, + IMAGE_HEIC_SEQUENCE, + IMAGE_HEIC, + IMAGE_HEIF_SEQUENCE, + IMAGE_HEIF, + IMAGE_JPEG, + IMAGE_PNG, + IMAGE_TIFF, + MULTIPART_MIXED, + TEXT_CSS, + TEXT_CSV, + TEXT_HTML, + TEXT_PLAIN, + TEXT_XML, + VIDEO_H264, + VIDEO_H265, + VIDEO_VP8, + APPLICATION_X_HESSIAN, + APPLICATION_X_JAVA_OBJECT, + APPLICATION_CLOUDEVENTS_JSON, + MESSAGE_X_RSOCKET_MIME_TYPE_V0, + MESSAGE_X_RSOCKET_ACCEPT_TIME_TYPES_V0, + MESSAGE_X_RSOCKET_AUTHENTICATION_V0, + MESSAGE_X_RSOCKET_TRACING_ZIPKIN_V0, + MESSAGE_X_RSOCKET_ROUTING_V0, + MESSAGE_X_RSOCKET_COMPOSITE_METADATA_V0, + ] +} diff --git a/rsocket/src/extension/mod.rs b/rsocket/src/extension/mod.rs index f59dd2c..df8bf80 100644 --- a/rsocket/src/extension/mod.rs +++ b/rsocket/src/extension/mod.rs @@ -1,5 +1,7 @@ mod composite; +mod mime; mod routing; -pub use composite::{CompositeMetadata, Metadata}; +pub use composite::{CompositeMetadata, CompositeMetadataBuilder, CompositeMetadataEntry}; +pub use mime::*; pub use routing::{RoutingMetadata, RoutingMetadataBuilder}; diff --git a/rsocket/src/extension/routing.rs b/rsocket/src/extension/routing.rs index ae68e9c..ca1e150 100644 --- a/rsocket/src/extension/routing.rs +++ b/rsocket/src/extension/routing.rs @@ -1,5 +1,4 @@ use crate::error::{ErrorKind, RSocketError}; -use crate::mime::WellKnownMIME; use crate::utils::{RSocketResult, Writeable, U24}; use bytes::{Buf, BufMut, Bytes, BytesMut}; diff --git a/rsocket/src/frame/error.rs b/rsocket/src/frame/error.rs index b8957d2..d7cff9a 100644 --- a/rsocket/src/frame/error.rs +++ b/rsocket/src/frame/error.rs @@ -43,7 +43,7 @@ impl ErrorBuilder { } impl Error { - pub fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { let code = bf.get_u32(); let d: Option = if !bf.is_empty() { Some(bf.to_bytes()) @@ -57,15 +57,18 @@ impl Error { ErrorBuilder::new(stream_id, flag) } - pub fn get_data_utf8(&self) -> String { - match self.get_data() { - Some(b) => String::from_utf8(b.to_vec()).unwrap(), - None => String::from(""), + pub fn get_data_utf8(&self) -> Option<&str> { + match &self.data { + Some(b) => Some(std::str::from_utf8(b.as_ref()).expect("Invalid UTF-8 bytes.")), + None => None, } } - pub fn get_data(&self) -> &Option { - &self.data + pub fn get_data(&self) -> Option<&Bytes> { + match &self.data { + Some(b) => Some(b), + None => None, + } } pub fn get_code(&self) -> u32 { diff --git a/rsocket/src/frame/keepalive.rs b/rsocket/src/frame/keepalive.rs index 8ee4a89..c1826ea 100644 --- a/rsocket/src/frame/keepalive.rs +++ b/rsocket/src/frame/keepalive.rs @@ -42,7 +42,7 @@ impl KeepaliveBuilder { } impl Keepalive { - pub fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { let position = bf.get_u64(); let mut d: Option = None; if !bf.is_empty() { @@ -62,8 +62,11 @@ impl Keepalive { self.last_received_position } - pub fn get_data(&self) -> &Option { - &self.data + pub fn get_data(&self) -> Option<&Bytes> { + match &self.data { + Some(b) => Some(b), + None => None, + } } pub fn split(self) -> (Option, Option) { diff --git a/rsocket/src/frame/lease.rs b/rsocket/src/frame/lease.rs index dee4b6c..fe4f7d6 100644 --- a/rsocket/src/frame/lease.rs +++ b/rsocket/src/frame/lease.rs @@ -50,7 +50,7 @@ impl LeaseBuilder { } impl Lease { - pub fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { let ttl = bf.get_u32(); let n = bf.get_u32(); let m = if flag & FLAG_METADATA != 0 { @@ -73,8 +73,11 @@ impl Lease { self.number_of_requests } - pub fn get_metadata(&self) -> &Option { - &self.metadata + pub fn get_metadata(&self) -> Option<&Bytes> { + match &self.metadata { + Some(b) => Some(b), + None => None, + } } pub fn get_ttl(&self) -> u32 { diff --git a/rsocket/src/frame/metadata_push.rs b/rsocket/src/frame/metadata_push.rs index e1d6b74..3d4939a 100644 --- a/rsocket/src/frame/metadata_push.rs +++ b/rsocket/src/frame/metadata_push.rs @@ -33,7 +33,7 @@ impl MetadataPushBuiler { } impl MetadataPush { - pub fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { let m = Bytes::from(bf.to_vec()); Ok(MetadataPush { metadata: Some(m) }) } @@ -42,8 +42,11 @@ impl MetadataPush { MetadataPushBuiler::new(stream_id, flag) } - pub fn get_metadata(&self) -> &Option { - &self.metadata + pub fn get_metadata(&self) -> Option<&Bytes> { + match &self.metadata { + Some(b) => Some(b), + None => None, + } } pub fn split(self) -> (Option, Option) { diff --git a/rsocket/src/frame/mod.rs b/rsocket/src/frame/mod.rs index 1dcecae..a28d1ee 100644 --- a/rsocket/src/frame/mod.rs +++ b/rsocket/src/frame/mod.rs @@ -182,10 +182,6 @@ impl Frame { self.body } - pub fn get_frame_type(&self) -> u16 { - to_frame_type(&self.body) - } - pub fn get_flag(&self) -> u16 { self.flag } diff --git a/rsocket/src/frame/payload.rs b/rsocket/src/frame/payload.rs index adc5931..9c44d65 100644 --- a/rsocket/src/frame/payload.rs +++ b/rsocket/src/frame/payload.rs @@ -58,7 +58,7 @@ impl PayloadBuilder { } impl Payload { - pub fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { let (m, d) = PayloadSupport::read(flag, bf); Ok(Payload { metadata: m, @@ -70,12 +70,18 @@ impl Payload { PayloadBuilder::new(stream_id, flag) } - pub fn get_metadata(&self) -> &Option { - &self.metadata + pub fn get_metadata(&self) -> Option<&Bytes> { + match &self.metadata { + Some(b) => Some(b), + None => None, + } } - pub fn get_data(&self) -> &Option { - &self.data + pub fn get_data(&self) -> Option<&Bytes> { + match &self.data { + Some(b) => Some(b), + None => None, + } } pub fn split(self) -> (Option, Option) { diff --git a/rsocket/src/frame/request_channel.rs b/rsocket/src/frame/request_channel.rs index ac7f333..7b5de50 100644 --- a/rsocket/src/frame/request_channel.rs +++ b/rsocket/src/frame/request_channel.rs @@ -65,7 +65,7 @@ impl RequestChannelBuilder { } impl RequestChannel { - pub fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { let n = bf.get_u32(); let (m, d) = PayloadSupport::read(flag, bf); Ok(RequestChannel { @@ -83,11 +83,17 @@ impl RequestChannel { self.initial_request_n } - pub fn get_metadata(&self) -> &Option { - &self.metadata + pub fn get_metadata(&self) -> Option<&Bytes> { + match &self.metadata { + Some(b) => Some(b), + None => None, + } } - pub fn get_data(&self) -> &Option { - &self.data + pub fn get_data(&self) -> Option<&Bytes> { + match &self.data { + Some(b) => Some(b), + None => None, + } } pub fn split(self) -> (Option, Option) { diff --git a/rsocket/src/frame/request_fnf.rs b/rsocket/src/frame/request_fnf.rs index 852eb89..f1d5817 100644 --- a/rsocket/src/frame/request_fnf.rs +++ b/rsocket/src/frame/request_fnf.rs @@ -58,7 +58,7 @@ impl RequestFNFBuilder { } impl RequestFNF { - pub fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { let (m, d) = PayloadSupport::read(flag, bf); Ok(RequestFNF { metadata: m, @@ -70,12 +70,18 @@ impl RequestFNF { RequestFNFBuilder::new(stream_id, flag) } - pub fn get_metadata(&self) -> &Option { - &self.metadata + pub fn get_metadata(&self) -> Option<&Bytes> { + match &self.metadata { + Some(b) => Some(b), + None => None, + } } - pub fn get_data(&self) -> &Option { - &self.data + pub fn get_data(&self) -> Option<&Bytes> { + match &self.data { + Some(b) => Some(b), + None => None, + } } pub fn split(self) -> (Option, Option) { diff --git a/rsocket/src/frame/request_n.rs b/rsocket/src/frame/request_n.rs index b2a6e4b..2144187 100644 --- a/rsocket/src/frame/request_n.rs +++ b/rsocket/src/frame/request_n.rs @@ -33,7 +33,7 @@ impl RequestNBuilder { } impl RequestN { - pub fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { let n = bf.get_u32(); Ok(RequestN { n }) } diff --git a/rsocket/src/frame/request_response.rs b/rsocket/src/frame/request_response.rs index effaaa0..b4c0da4 100644 --- a/rsocket/src/frame/request_response.rs +++ b/rsocket/src/frame/request_response.rs @@ -58,7 +58,7 @@ impl RequestResponseBuilder { } impl RequestResponse { - pub fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { let (m, d) = PayloadSupport::read(flag, bf); Ok(RequestResponse { metadata: m, @@ -70,12 +70,18 @@ impl RequestResponse { RequestResponseBuilder::new(stream_id, flag) } - pub fn get_metadata(&self) -> &Option { - &self.metadata + pub fn get_metadata(&self) -> Option<&Bytes> { + match &self.metadata { + Some(b) => Some(b), + None => None, + } } - pub fn get_data(&self) -> &Option { - &self.data + pub fn get_data(&self) -> Option<&Bytes> { + match &self.data { + Some(b) => Some(b), + None => None, + } } pub fn split(self) -> (Option, Option) { diff --git a/rsocket/src/frame/request_stream.rs b/rsocket/src/frame/request_stream.rs index d9787eb..9576f6b 100644 --- a/rsocket/src/frame/request_stream.rs +++ b/rsocket/src/frame/request_stream.rs @@ -53,7 +53,7 @@ impl RequestStreamBuilder { } impl RequestStream { - pub fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { let n = bf.get_u32(); let (m, d) = PayloadSupport::read(flag, bf); Ok(RequestStream { @@ -79,12 +79,18 @@ impl RequestStream { self.initial_request_n } - pub fn get_metadata(&self) -> &Option { - &self.metadata + pub fn get_metadata(&self) -> Option<&Bytes> { + match &self.metadata { + Some(b) => Some(b), + None => None, + } } - pub fn get_data(&self) -> &Option { - &self.data + pub fn get_data(&self) -> Option<&Bytes> { + match &self.data { + Some(b) => Some(b), + None => None, + } } pub fn split(self) -> (Option, Option) { diff --git a/rsocket/src/frame/resume.rs b/rsocket/src/frame/resume.rs index 71daf9a..4898449 100644 --- a/rsocket/src/frame/resume.rs +++ b/rsocket/src/frame/resume.rs @@ -26,7 +26,7 @@ impl Resume { } } - pub fn decode(flag: u16, b: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, b: &mut BytesMut) -> RSocketResult { let major = b.get_u16(); let minor = b.get_u16(); let token_size = b.get_u16(); diff --git a/rsocket/src/frame/resume_ok.rs b/rsocket/src/frame/resume_ok.rs index f1eaa79..a02a525 100644 --- a/rsocket/src/frame/resume_ok.rs +++ b/rsocket/src/frame/resume_ok.rs @@ -32,7 +32,7 @@ impl ResumeOKBuilder { } impl ResumeOK { - pub fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { let position = bf.get_u64(); Ok(ResumeOK { position }) } diff --git a/rsocket/src/frame/setup.rs b/rsocket/src/frame/setup.rs index 499e28c..a16919c 100644 --- a/rsocket/src/frame/setup.rs +++ b/rsocket/src/frame/setup.rs @@ -9,66 +9,44 @@ pub struct Setup { keepalive: u32, lifetime: u32, token: Option, - mime_metadata: String, - mime_data: String, + mime_metadata: Bytes, + mime_data: Bytes, metadata: Option, data: Option, } -impl Writeable for Setup { - fn len(&self) -> usize { - let mut n: usize = 12; - n += match &self.token { - Some(v) => 2 + v.len(), - None => 0, - }; - n += 2 + self.mime_metadata.len() + self.mime_data.len(); - n += PayloadSupport::len(&self.metadata, &self.data); - n - } - - fn write_to(&self, bf: &mut BytesMut) { - self.version.write_to(bf); - bf.put_u32(self.keepalive); - bf.put_u32(self.lifetime); - if let Some(b) = &self.token { - bf.put_u16(b.len() as u16); - bf.put(b.bytes()); - } - bf.put_u8(self.mime_metadata.len() as u8); - bf.put(Bytes::from(self.mime_metadata.clone())); - bf.put_u8(self.mime_data.len() as u8); - bf.put(Bytes::from(self.mime_data.clone())); - PayloadSupport::write(bf, self.get_metadata(), self.get_data()); - } +pub struct SetupBuilder { + stream_id: u32, + flag: u16, + value: Setup, } impl Setup { - pub fn decode(flag: u16, b: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, b: &mut BytesMut) -> RSocketResult { let major = b.get_u16(); let minor = b.get_u16(); let keepalive = b.get_u32(); let lifetime = b.get_u32(); let token: Option = if flag & FLAG_RESUME != 0 { let l = b.get_u16(); - Some(b.split_to(l as usize).to_bytes()) + Some(b.split_to(l as usize).freeze()) } else { None }; let mut len_mime: usize = b[0] as usize; b.advance(1); - let mime_metadata = b.split_to(len_mime); + let mime_metadata = b.split_to(len_mime).freeze(); len_mime = b[0] as usize; b.advance(1); - let mime_data = b.split_to(len_mime); + let mime_data = b.split_to(len_mime).freeze(); let (metadata, data) = PayloadSupport::read(flag, b); Ok(Setup { version: Version::new(major, minor), keepalive, lifetime, token, - mime_metadata: String::from_utf8(mime_metadata.to_vec()).unwrap(), - mime_data: String::from_utf8(mime_data.to_vec()).unwrap(), + mime_metadata, + mime_data, metadata, data, }) @@ -90,24 +68,33 @@ impl Setup { Duration::from_millis(u64::from(self.lifetime)) } - pub fn get_token(&self) -> Option { - self.token.clone() + pub fn get_token(&self) -> Option<&Bytes> { + match &self.token { + Some(b) => Some(b), + None => None, + } } pub fn get_mime_metadata(&self) -> &str { - &self.mime_metadata + std::str::from_utf8(self.mime_metadata.as_ref()).expect("Invalid UTF-8 bytes.") } pub fn get_mime_data(&self) -> &str { - &self.mime_data + std::str::from_utf8(self.mime_data.as_ref()).expect("Invalid UTF-8 bytes.") } - pub fn get_metadata(&self) -> &Option { - &self.metadata + pub fn get_metadata(&self) -> Option<&Bytes> { + match &self.metadata { + Some(b) => Some(b), + None => None, + } } - pub fn get_data(&self) -> &Option { - &self.data + pub fn get_data(&self) -> Option<&Bytes> { + match &self.data { + Some(b) => Some(b), + None => None, + } } pub fn split(self) -> (Option, Option) { @@ -115,10 +102,32 @@ impl Setup { } } -pub struct SetupBuilder { - stream_id: u32, - flag: u16, - value: Setup, +impl Writeable for Setup { + fn len(&self) -> usize { + let mut n: usize = 12; + n += match &self.token { + Some(v) => 2 + v.len(), + None => 0, + }; + n += 2 + self.mime_metadata.len() + self.mime_data.len(); + n += PayloadSupport::len(self.get_metadata(), self.get_data()); + n + } + + fn write_to(&self, bf: &mut BytesMut) { + self.version.write_to(bf); + bf.put_u32(self.keepalive); + bf.put_u32(self.lifetime); + if let Some(b) = &self.token { + bf.put_u16(b.len() as u16); + bf.put(b.bytes()); + } + bf.put_u8(self.mime_metadata.len() as u8); + bf.put(self.mime_metadata.clone()); + bf.put_u8(self.mime_data.len() as u8); + bf.put(self.mime_data.clone()); + PayloadSupport::write(bf, self.get_metadata(), self.get_data()); + } } impl SetupBuilder { @@ -131,8 +140,8 @@ impl SetupBuilder { keepalive: 30_000, lifetime: 90_000, token: None, - mime_metadata: String::from(DEFAULT_MIME_TYPE), - mime_data: String::from(DEFAULT_MIME_TYPE), + mime_metadata: Bytes::from(DEFAULT_MIME_TYPE), + mime_data: Bytes::from(DEFAULT_MIME_TYPE), metadata: None, data: None, }, @@ -175,19 +184,27 @@ impl SetupBuilder { self } - pub fn set_mime_metadata(mut self, mime: &str) -> Self { + pub fn set_mime_metadata(mut self, mime: I) -> Self + where + I: Into, + { + let mime = mime.into(); if mime.len() > 256 { panic!("maximum mime length is 256"); } - self.value.mime_metadata = String::from(mime); + self.value.mime_metadata = Bytes::from(mime); self } - pub fn set_mime_data(mut self, mime: &str) -> Self { + pub fn set_mime_data(mut self, mime: I) -> Self + where + I: Into, + { + let mime = mime.into(); if mime.len() > 256 { panic!("maximum mime length is 256"); } - self.value.mime_data = String::from(mime); + self.value.mime_data = Bytes::from(mime); self } } diff --git a/rsocket/src/frame/utils.rs b/rsocket/src/frame/utils.rs index 465a5bd..7f6e818 100644 --- a/rsocket/src/frame/utils.rs +++ b/rsocket/src/frame/utils.rs @@ -5,7 +5,7 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; pub(crate) struct PayloadSupport {} impl PayloadSupport { - pub fn len(metadata: &Option, data: &Option) -> usize { + pub fn len(metadata: Option<&Bytes>, data: Option<&Bytes>) -> usize { let a = match metadata { Some(v) => 3 + v.len(), None => 0, @@ -20,7 +20,7 @@ impl PayloadSupport { pub fn read(flag: u16, bf: &mut BytesMut) -> (Option, Option) { let m: Option = if flag & FLAG_METADATA != 0 { let n = U24::read_advance(bf); - Some(bf.split_to(n as usize).to_bytes()) + Some(bf.split_to(n as usize).freeze()) } else { None }; @@ -32,14 +32,14 @@ impl PayloadSupport { (m, d) } - pub fn write(bf: &mut BytesMut, metadata: &Option, data: &Option) { + pub fn write(bf: &mut BytesMut, metadata: Option<&Bytes>, data: Option<&Bytes>) { if let Some(v) = metadata { let n = v.len() as u32; U24::write(n, bf); - bf.put(v.bytes()); + bf.put(v.clone()); } if let Some(v) = data { - bf.put(v.bytes()) + bf.put(v.clone()) } } } diff --git a/rsocket/src/lib.rs b/rsocket/src/lib.rs index 194dc6f..468c04d 100644 --- a/rsocket/src/lib.rs +++ b/rsocket/src/lib.rs @@ -102,7 +102,6 @@ pub mod frame; #[cfg(not(feature = "frame"))] mod frame; -pub mod mime; mod payload; pub mod prelude; pub mod runtime; diff --git a/rsocket/src/mime.rs b/rsocket/src/mime.rs deleted file mode 100644 index ac958f0..0000000 --- a/rsocket/src/mime.rs +++ /dev/null @@ -1,256 +0,0 @@ -use std::collections::HashMap; -use std::fmt; - -pub const APPLICATION_BINARY: &str = "application/binary"; -pub const APPLICATION_AVRO: &str = "application/avro"; -pub const APPLICATION_CBOR: &str = "application/cbor"; -pub const APPLICATION_GRAPHQL: &str = "application/graphql"; -pub const APPLICATION_GZIP: &str = "application/gzip"; -pub const APPLICATION_JAVASCRIPT: &str = "application/javascript"; -pub const APPLICATION_JSON: &str = "application/json"; -pub const APPLICATION_OCTET_STREAM: &str = "application/octet-stream"; -pub const APPLICATION_PDF: &str = "application/pdf"; -pub const APPLICATION_THRIFT: &str = "application/vnd.apache.thrift.binary"; -pub const APPLICATION_PROTOBUF: &str = "application/vnd.google.protobuf"; -pub const APPLICATION_XML: &str = "application/xml"; -pub const APPLICATION_ZIP: &str = "application/zip"; -pub const AUDIO_AAC: &str = "audio/aac"; -pub const AUDIO_MP3: &str = "audio/mp3"; -pub const AUDIO_MP4: &str = "audio/mp4"; -pub const AUDIO_MPEG3: &str = "audio/mpeg3"; -pub const AUDIO_MPEG: &str = "audio/mpeg"; -pub const AUDIO_OGG: &str = "audio/ogg"; -pub const AUDIO_OPUS: &str = "audio/opus"; -pub const AUDIO_VORBIS: &str = "audio/vorbis"; -pub const IMAGE_BMP: &str = "image/bmp"; -pub const IMAGE_GIF: &str = "image/gif"; -pub const IMAGE_HEIC_SEQUENCE: &str = "image/heic-sequence"; -pub const IMAGE_HEIC: &str = "image/heic"; -pub const IMAGE_HEIF_SEQUENCE: &str = "image/heif-sequence"; -pub const IMAGE_HEIF: &str = "image/heif"; -pub const IMAGE_JPEG: &str = "image/jpeg"; -pub const IMAGE_PNG: &str = "image/png"; -pub const IMAGE_TIFF: &str = "image/tiff"; -pub const MULTIPART_MIXED: &str = "multipart/mixed"; -pub const TEXT_CSS: &str = "text/css"; -pub const TEXT_CSV: &str = "text/csv"; -pub const TEXT_HTML: &str = "text/html"; -pub const TEXT_PLAIN: &str = "text/plain"; -pub const TEXT_XML: &str = "text/xml"; -pub const VIDEO_H264: &str = "video/H264"; -pub const VIDEO_H265: &str = "video/H265"; -pub const VIDEO_VP8: &str = "video/VP8"; -pub const APPLICATION_X_HESSIAN: &str = "application/x-hessian"; -pub const APPLICATION_X_JAVA_OBJECT: &str = "application/x-java-object"; -pub const APPLICATION_CLOUDEVENTS_JSON: &str = "application/cloudevents+json"; -pub const MESSAGE_X_RSOCKET_TRACING_ZIPKIN_V0: &str = "message/x.rsocket.tracing-zipkin.v0"; -pub const MESSAGE_X_RSOCKET_ROUTING_V0: &str = "message/x.rsocket.routing.v0"; -pub const MESSAGE_X_RSOCKET_COMPOSITE_METADATA_V0: &str = "message/x.rsocket.composite-metadata.v0"; - -lazy_static! { - static ref MIME_MAP: HashMap = { - let mut m = HashMap::new(); - m.insert(WellKnownMIME::ApplicationAvro, (0x00, APPLICATION_AVRO)); - m.insert(WellKnownMIME::ApplicationCbor, (0x01, APPLICATION_CBOR)); - m.insert( - WellKnownMIME::ApplicationGraphql, - (0x02, APPLICATION_GRAPHQL), - ); - m.insert(WellKnownMIME::ApplicationGzip, (0x03, APPLICATION_GZIP)); - m.insert( - WellKnownMIME::ApplicationJavascript, - (0x04, APPLICATION_JAVASCRIPT), - ); - m.insert(WellKnownMIME::ApplicationJson, (0x05, APPLICATION_JSON)); - m.insert( - WellKnownMIME::ApplicationOctetStream, - (0x06, APPLICATION_OCTET_STREAM), - ); - m.insert(WellKnownMIME::ApplicationPdf, (0x07, APPLICATION_PDF)); - m.insert( - WellKnownMIME::ApplicationVndApacheThriftBinary, - (0x08, APPLICATION_THRIFT), - ); - m.insert( - WellKnownMIME::ApplicationVndGoogleProtobuf, - (0x09, APPLICATION_PROTOBUF), - ); - m.insert(WellKnownMIME::ApplicationXml, (0x0A, APPLICATION_XML)); - m.insert(WellKnownMIME::ApplicationZip, (0x0B, APPLICATION_ZIP)); - m.insert(WellKnownMIME::AudioAac, (0x0C, AUDIO_AAC)); - m.insert(WellKnownMIME::AudioMp3, (0x0D, AUDIO_MP3)); - m.insert(WellKnownMIME::AudioMp4, (0x0E, AUDIO_MP4)); - m.insert(WellKnownMIME::AudioMpeg3, (0x0F, AUDIO_MPEG3)); - m.insert(WellKnownMIME::AudioMpeg, (0x10, AUDIO_MPEG)); - m.insert(WellKnownMIME::AudioOgg, (0x11, AUDIO_OGG)); - m.insert(WellKnownMIME::AudioOpus, (0x12, AUDIO_OPUS)); - m.insert(WellKnownMIME::AudioVorbis, (0x13, AUDIO_VORBIS)); - m.insert(WellKnownMIME::ImageBmp, (0x14, IMAGE_BMP)); - m.insert(WellKnownMIME::ImageGif, (0x15, IMAGE_GIF)); - m.insert( - WellKnownMIME::ImageHeicSequence, - (0x16, IMAGE_HEIC_SEQUENCE), - ); - m.insert(WellKnownMIME::ImageHeic, (0x17, IMAGE_HEIC)); - m.insert( - WellKnownMIME::ImageHeifSequence, - (0x18, IMAGE_HEIF_SEQUENCE), - ); - m.insert(WellKnownMIME::ImageHeif, (0x19, IMAGE_HEIF)); - m.insert(WellKnownMIME::ImageJpeg, (0x1A, IMAGE_JPEG)); - m.insert(WellKnownMIME::ImagePng, (0x1B, IMAGE_PNG)); - m.insert(WellKnownMIME::ImageTiff, (0x1C, IMAGE_TIFF)); - m.insert(WellKnownMIME::MultipartMixed, (0x1D, MULTIPART_MIXED)); - m.insert(WellKnownMIME::TextCss, (0x1E, TEXT_CSS)); - m.insert(WellKnownMIME::TextCsv, (0x1F, TEXT_CSV)); - m.insert(WellKnownMIME::TextHtml, (0x20, TEXT_HTML)); - m.insert(WellKnownMIME::TextPlain, (0x21, TEXT_PLAIN)); - m.insert(WellKnownMIME::TextXml, (0x22, TEXT_XML)); - m.insert(WellKnownMIME::VideoH264, (0x23, VIDEO_H264)); - m.insert(WellKnownMIME::VideoH265, (0x24, VIDEO_H265)); - m.insert(WellKnownMIME::VideoVP8, (0x25, VIDEO_VP8)); - m.insert( - WellKnownMIME::ApplicationXHessian, - (0x26, APPLICATION_X_HESSIAN), - ); - m.insert( - WellKnownMIME::ApplicationXJavaObject, - (0x27, APPLICATION_X_JAVA_OBJECT), - ); - m.insert( - WellKnownMIME::ApplicationCloudeventsJson, - (0x28, APPLICATION_CLOUDEVENTS_JSON), - ); - m.insert( - WellKnownMIME::MessageXRSocketTracingZipkinV0, - (0x7D, MESSAGE_X_RSOCKET_TRACING_ZIPKIN_V0), - ); - m.insert( - WellKnownMIME::MessageXRSocketRoutingV0, - (0x7E, MESSAGE_X_RSOCKET_ROUTING_V0), - ); - m.insert( - WellKnownMIME::MessageXRsocketCompositeMetadataV0, - (0x7F, MESSAGE_X_RSOCKET_COMPOSITE_METADATA_V0), - ); - m - }; -} - -#[derive(PartialEq, Eq, Debug, Clone, Hash)] -pub enum WellKnownMIME { - ApplicationAvro, - ApplicationCbor, - ApplicationGraphql, - ApplicationGzip, - ApplicationJavascript, - ApplicationJson, - ApplicationOctetStream, - ApplicationPdf, - ApplicationVndApacheThriftBinary, - ApplicationVndGoogleProtobuf, - ApplicationXml, - ApplicationZip, - AudioAac, - AudioMp3, - AudioMp4, - AudioMpeg3, - AudioMpeg, - AudioOgg, - AudioOpus, - AudioVorbis, - ImageBmp, - ImageGif, - ImageHeicSequence, - ImageHeic, - ImageHeifSequence, - ImageHeif, - ImageJpeg, - ImagePng, - ImageTiff, - MultipartMixed, - TextCss, - TextCsv, - TextHtml, - TextPlain, - TextXml, - VideoH264, - VideoH265, - VideoVP8, - ApplicationXHessian, - ApplicationXJavaObject, - ApplicationCloudeventsJson, - MessageXRSocketTracingZipkinV0, - MessageXRSocketRoutingV0, - MessageXRsocketCompositeMetadataV0, - Unknown, -} - -impl WellKnownMIME { - pub fn foreach(f: impl Fn(&WellKnownMIME)) { - for k in MIME_MAP.keys() { - f(k); - } - } - - pub fn str(&self) -> &'static str { - let (_, s) = MIME_MAP.get(self).unwrap(); - s - } - - pub fn raw(&self) -> u8 { - let (v, _) = MIME_MAP.get(self).unwrap(); - *v - } -} - -impl From for WellKnownMIME { - fn from(s: String) -> WellKnownMIME { - let mut result = WellKnownMIME::Unknown; - for (k, v) in MIME_MAP.iter() { - let (_, vv) = v; - if *vv == s { - result = k.clone(); - break; - } - } - result - } -} - -impl From<&str> for WellKnownMIME { - fn from(s: &str) -> WellKnownMIME { - let mut result = WellKnownMIME::Unknown; - for (k, v) in MIME_MAP.iter() { - let (_, vv) = v; - if *vv == s { - result = k.clone(); - break; - } - } - result - } -} - -impl From for WellKnownMIME { - fn from(n: u8) -> WellKnownMIME { - let mut result = WellKnownMIME::Unknown; - for (k, v) in MIME_MAP.iter() { - let (a, _) = v; - if *a == n { - result = k.clone(); - break; - } - } - result - } -} - -impl fmt::Display for WellKnownMIME { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match MIME_MAP.get(self) { - Some((_, v)) => write!(f, "{}", v), - None => write!(f, "unknown"), - } - } -} diff --git a/rsocket/src/payload/normal.rs b/rsocket/src/payload/normal.rs index df1e913..8189ffb 100644 --- a/rsocket/src/payload/normal.rs +++ b/rsocket/src/payload/normal.rs @@ -62,24 +62,32 @@ impl Payload { PayloadBuilder::new() } - pub fn metadata(&self) -> &Option { - &self.m + pub fn metadata(&self) -> Option<&Bytes> { + match &self.m { + Some(b) => Some(b), + None => None, + } } - pub fn data(&self) -> &Option { - &self.d + pub fn data(&self) -> Option<&Bytes> { + match &self.d { + Some(b) => Some(b), + None => None, + } } - pub fn data_utf8(&self) -> Option { - self.d - .as_ref() - .map(|raw| String::from_utf8(raw.to_vec()).unwrap()) + pub fn data_utf8(&self) -> Option<&str> { + match &self.d { + Some(b) => Some(std::str::from_utf8(b.as_ref()).expect("Invalid UTF-8 bytes.")), + None => None, + } } - pub fn metadata_utf8(&self) -> Option { - self.m - .as_ref() - .map(|raw| String::from_utf8(raw.to_vec()).unwrap()) + pub fn metadata_utf8(&self) -> Option<&str> { + match &self.m { + Some(b) => Some(std::str::from_utf8(b.as_ref()).expect("Invalid UTF-8 bytes.")), + None => None, + } } pub fn is_empty(&self) -> bool { diff --git a/rsocket/src/payload/setup.rs b/rsocket/src/payload/setup.rs index 1abe197..a070b3b 100644 --- a/rsocket/src/payload/setup.rs +++ b/rsocket/src/payload/setup.rs @@ -98,12 +98,18 @@ impl SetupPayloadBuilder { } impl SetupPayload { - pub fn metadata(&self) -> &Option { - &self.m + pub fn metadata(&self) -> Option<&Bytes> { + match &self.m { + Some(b) => Some(b), + None => None, + } } - pub fn data(&self) -> &Option { - &self.d + pub fn data(&self) -> Option<&Bytes> { + match &self.d { + Some(b) => Some(b), + None => None, + } } pub fn split(self) -> (Option, Option) { @@ -118,16 +124,18 @@ impl SetupPayload { self.keepalive.1 } - pub fn metadata_mime_type(&self) -> Option { - self.mime_m - .as_ref() - .map(|raw| String::from_utf8(raw.to_vec()).expect("read metadata MIME type failed!")) + pub fn metadata_mime_type(&self) -> Option<&str> { + match &self.mime_m { + Some(b) => Some(std::str::from_utf8(b.as_ref()).expect("Invalid UTF-8 bytes.")), + None => None, + } } - pub fn data_mime_type(&self) -> Option { - self.mime_d - .as_ref() - .map(|raw| String::from_utf8(raw.to_vec()).expect("read data MIME type failed!")) + pub fn data_mime_type(&self) -> Option<&str> { + match &self.mime_d { + Some(b) => Some(std::str::from_utf8(b.as_ref()).expect("Invalid UTF-8 bytes.")), + None => None, + } } } diff --git a/rsocket/src/transport/fragmentation.rs b/rsocket/src/transport/fragmentation.rs index 1736191..fdbcf4a 100644 --- a/rsocket/src/transport/fragmentation.rs +++ b/rsocket/src/transport/fragmentation.rs @@ -126,10 +126,6 @@ impl Joiner { self.first().get_flag() & !frame::FLAG_FOLLOW } - pub(crate) fn get_frame_type(&self) -> u16 { - self.first().get_frame_type() - } - pub(crate) fn first(&self) -> &Frame { self.inner.front().expect("No frames pushed!") } diff --git a/rsocket/src/transport/socket.rs b/rsocket/src/transport/socket.rs index bd25141..0759a1a 100644 --- a/rsocket/src/transport/socket.rs +++ b/rsocket/src/transport/socket.rs @@ -29,7 +29,7 @@ where seq: StreamID, responder: Responder, tx: Tx, - handlers: Arc>>, + handlers: [Arc>>; 16], canceller: Tx, splitter: Option, joiners: Arc>>, @@ -60,13 +60,31 @@ where ) -> DuplexSocket { let rt2 = rt.clone(); let (canceller_tx, canceller_rx) = new_tx_rx::(); + let handlers = [ + Arc::new(Mutex::new(HashMap::new())), + Arc::new(Mutex::new(HashMap::new())), + Arc::new(Mutex::new(HashMap::new())), + Arc::new(Mutex::new(HashMap::new())), + Arc::new(Mutex::new(HashMap::new())), + Arc::new(Mutex::new(HashMap::new())), + Arc::new(Mutex::new(HashMap::new())), + Arc::new(Mutex::new(HashMap::new())), + Arc::new(Mutex::new(HashMap::new())), + Arc::new(Mutex::new(HashMap::new())), + Arc::new(Mutex::new(HashMap::new())), + Arc::new(Mutex::new(HashMap::new())), + Arc::new(Mutex::new(HashMap::new())), + Arc::new(Mutex::new(HashMap::new())), + Arc::new(Mutex::new(HashMap::new())), + Arc::new(Mutex::new(HashMap::new())), + ]; let ds = DuplexSocket { rt, seq: StreamID::from(first_stream_id), tx, canceller: canceller_tx, responder: Responder::new(), - handlers: Arc::new(Mutex::new(HashMap::new())), + handlers, joiners: Arc::new(Mutex::new(HashMap::new())), splitter, }; @@ -85,10 +103,10 @@ where pub(crate) async fn setup(&self, setup: SetupPayload) { let mut bu = frame::Setup::builder(0, 0); if let Some(s) = setup.data_mime_type() { - bu = bu.set_mime_data(&s); + bu = bu.set_mime_data(s); } if let Some(s) = setup.metadata_mime_type() { - bu = bu.set_mime_metadata(&s); + bu = bu.set_mime_metadata(s); } bu = bu.set_keepalive(setup.keepalive_interval()); bu = bu.set_lifetime(setup.keepalive_lifetime()); @@ -104,16 +122,22 @@ where .expect("Send setup failed"); } + #[inline] + fn get_handler(&self, sid: u32) -> &Arc>> { + let i = ((sid ^ (sid >> 16)) & 15) as usize; + &self.handlers[i] + } + #[inline] async fn register_handler(&self, sid: u32, handler: Handler) { - let mut handlers = self.handlers.lock().await; + let h = self.get_handler(sid); + let mut handlers = h.lock().await; (*handlers).insert(sid, handler); } - #[inline] pub(crate) async fn loop_canceller(&self, mut rx: Rx) { while let Some(sid) = rx.next().await { - let mut handlers = self.handlers.lock().await; + let mut handlers = self.get_handler(sid).lock().await; (*handlers).remove(&sid); } } @@ -197,6 +221,7 @@ where } } + #[inline] async fn join_frame(&self, input: Frame) -> Option { let (is_follow, is_payload) = input.is_followable_or_payload(); if !is_follow { @@ -277,9 +302,10 @@ where (*joiners).remove(&sid); } // pick handler - let mut handlers = self.handlers.lock().await; + let mut handlers = self.get_handler(sid).lock().await; if let Some(handler) = (*handlers).remove(&sid) { - let kind = ErrorKind::Internal(input.get_code(), input.get_data_utf8()); + let kind = + ErrorKind::Internal(input.get_code(), input.get_data_utf8().unwrap().to_owned()); let e = Err(RSocketError::from(kind)); match handler { Handler::ReqRR(tx) => tx.send(e).expect("Send RR failed"), @@ -296,7 +322,7 @@ where let mut joiners = self.joiners.lock().await; (*joiners).remove(&sid); } - let mut handlers = self.handlers.lock().await; + let mut handlers = self.get_handler(sid).lock().await; if let Some(handler) = (*handlers).remove(&sid) { let e = Err(RSocketError::from(ErrorKind::Cancelled())); match handler { @@ -320,7 +346,7 @@ where #[inline] async fn on_payload(&self, sid: u32, flag: u16, input: Payload) { - let mut handlers = self.handlers.lock().await; + let mut handlers = self.get_handler(sid).lock().await; // fire event! match (*handlers).entry(sid) { Entry::Occupied(o) => { @@ -726,7 +752,7 @@ where fn request_response(&self, req: Payload) -> Mono> { let (tx, rx) = new_tx_rx_once::>(); let sid = self.seq.next(); - let handlers = Arc::clone(&self.handlers); + let handlers = Arc::clone(&self.get_handler(sid)); let sender = self.tx.clone(); let splitter = self.splitter.clone(); @@ -806,7 +832,7 @@ where let tx = self.tx.clone(); // register handler let (sender, receiver) = new_tx_rx::>(); - let handlers = Arc::clone(&self.handlers); + let handlers = Arc::clone(&self.get_handler(sid)); let splitter = self.splitter.clone(); self.rt.spawn(async move { { @@ -878,7 +904,7 @@ where let tx = self.tx.clone(); // register handler let (sender, receiver) = new_tx_rx::>(); - let handlers = Arc::clone(&self.handlers); + let handlers = Arc::clone(&self.get_handler(sid)); let splitter = self.splitter.clone(); self.rt.spawn(async move { { From 5270ac9dcb681679766b702477827784778950bf Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Wed, 6 May 2020 23:12:33 +0800 Subject: [PATCH 04/70] foobar --- rsocket-messaging/src/lib.rs | 2 +- rsocket-messaging/src/requester.rs | 117 ++++++++++++++++++++++----- rsocket-test/tests/test_messaging.rs | 11 ++- 3 files changed, 108 insertions(+), 22 deletions(-) diff --git a/rsocket-messaging/src/lib.rs b/rsocket-messaging/src/lib.rs index 689dff2..5b8d09f 100644 --- a/rsocket-messaging/src/lib.rs +++ b/rsocket-messaging/src/lib.rs @@ -4,4 +4,4 @@ extern crate log; mod misc; mod requester; -pub use requester::{RequestSpec, Requester}; +pub use requester::{RequestSpec, Requester, RequesterBuilder}; diff --git a/rsocket-messaging/src/requester.rs b/rsocket-messaging/src/requester.rs index 5218a3b..0c661a7 100644 --- a/rsocket-messaging/src/requester.rs +++ b/rsocket-messaging/src/requester.rs @@ -11,6 +11,55 @@ use serde::{Deserialize, Serialize}; use std::collections::LinkedList; use std::error::Error; +pub struct RequesterBuilder { + data_mime_type: MimeType, + route: Option, + data: Option>, +} + +impl Default for RequesterBuilder { + fn default() -> Self { + Self { + data_mime_type: MIME_APPLICATION_JSON, + route: None, + data: None, + } + } +} + +impl RequesterBuilder { + pub fn data_mime_type(mut self, mime_type: I) -> Self + where + I: Into, + { + self.data_mime_type = mime_type.into(); + self + } + + pub fn setup_route(mut self, route: I) -> Self + where + I: Into, + { + self.route = Some(route.into()); + self + } + + pub fn setup_data(mut self, data: D) -> Self + where + D: Into>, + { + self.data = Some(data.into()); + self + } + + pub fn build(self) -> Requester + where + S: RSocket + Clone, + { + todo!("build requester") + } +} + pub struct Requester where S: RSocket + Clone, @@ -22,20 +71,25 @@ pub struct RequestSpec where S: RSocket + Clone, { - data_buf: BytesMut, + data: Option>, rsocket: S, data_mime_type: MimeType, metadatas: LinkedList<(MimeType, Vec)>, } -impl Requester +impl From for Requester where - C: RSocket + Clone, + S: RSocket + Clone, { - pub fn new(rsocket: C) -> Requester { + fn from(rsocket: S) -> Requester { Requester { rsocket } } +} +impl Requester +where + C: RSocket + Clone, +{ pub fn route(&self, route: &str) -> RequestSpec { let routing = RoutingMetadata::builder().push_str(route).build(); let mut buf = BytesMut::new(); @@ -44,7 +98,7 @@ where let mut metadatas: LinkedList<(MimeType, Vec)> = Default::default(); metadatas.push_back((MIME_MESSAGE_X_RSOCKET_ROUTING_V0, buf.to_vec())); RequestSpec { - data_buf: BytesMut::new(), + data: None, rsocket: self.rsocket.clone(), data_mime_type: MIME_APPLICATION_JSON, metadatas, @@ -56,44 +110,69 @@ impl RequestSpec where C: RSocket + Clone, { - pub fn metadata(&mut self, metadata: &T, mime_type: &str) -> Result<(), Box> + pub fn metadata(&mut self, metadata: &T, mime_type: M) -> Result<(), Box> where T: Sized + Serialize, + M: Into, { - let mime_type = MimeType::from(mime_type); + let mime_type = mime_type.into(); let mut b = BytesMut::new(); marshal(&mime_type, &mut b, metadata)?; self.metadatas.push_back((mime_type, b.to_vec())); Ok(()) } + pub fn metadata_raw(&mut self, metadata: I, mime_type: M) -> Result<(), Box> + where + I: Into>, + M: Into, + { + self.metadatas + .push_back((mime_type.into(), metadata.into())); + Ok(()) + } + pub fn data(&mut self, data: &T) -> Result<(), Box> where T: Sized + Serialize, { - marshal(&self.data_mime_type, &mut self.data_buf, data) + let mut bf = BytesMut::new(); + marshal(&self.data_mime_type, &mut bf, data)?; + self.data = Some(bf.to_vec()); + Ok(()) } - pub async fn retrieve_mono(&self) -> Unpacker { - let req = self.to_req(); - let res = self.rsocket.request_response(req).await; + pub fn data_raw(&mut self, data: I) -> Result<(), Box> + where + I: Into>, + { + self.data = Some(data.into()); + Ok(()) + } + + pub async fn retrieve_mono(self) -> Unpacker { + let (req, mime_type, rsocket) = self.preflight(); + let res = rsocket.request_response(req).await; Unpacker { - mime_type: self.data_mime_type.clone(), + mime_type, inner: res, } } - fn to_req(&self) -> Payload { + #[inline] + fn preflight(self) -> (Payload, MimeType, C) { let mut b = BytesMut::new(); let mut c = CompositeMetadata::builder(); - for (a, b) in self.metadatas.iter() { - c = c.push(a.clone(), b); + for (mime_type, raw) in self.metadatas.into_iter() { + c = c.push(mime_type, raw); } c.build().write_to(&mut b); - Payload::builder() - .set_metadata(b.to_vec()) - .set_data(self.data_buf.to_vec()) - .build() + + let mut bu = Payload::builder().set_metadata(b.to_vec()); + if let Some(raw) = self.data { + bu = bu.set_data(raw); + } + (bu.build(), self.data_mime_type, self.rsocket) } } diff --git a/rsocket-test/tests/test_messaging.rs b/rsocket-test/tests/test_messaging.rs index 23e9fc2..f4dcb92 100644 --- a/rsocket-test/tests/test_messaging.rs +++ b/rsocket-test/tests/test_messaging.rs @@ -32,7 +32,7 @@ async fn test_messaging() { .start() .await .expect("Connect failed!"); - let requester = Requester::new(rsocket); + let requester = Requester::from(rsocket); let post = Student { id: 1234, @@ -40,6 +40,9 @@ async fn test_messaging() { birth: "2020-01-01".to_owned(), }; let mut req = requester.route("student.v1.upsert"); + req.metadata_raw("raw metadata", "application/json") + .unwrap(); + req.metadata(&post, "application/json").unwrap(); req.data(&post).unwrap(); let res: Response = req .retrieve_mono() @@ -48,5 +51,9 @@ async fn test_messaging() { .expect("Retrieve failed!") .expect("Empty result!"); println!("------> RESPONSE: {:?}", res); - () +} + +#[test] +fn test_builder() { + RequesterBuilder::default().data_mime_type("application/json"); } From 08c5679e442db42b29bf3b93ca1058bf6aa112c5 Mon Sep 17 00:00:00 2001 From: caiweiwei03 Date: Fri, 8 May 2020 21:08:34 +0800 Subject: [PATCH 05/70] add benchmark. --- .gitignore | 4 ++- Cargo.toml | 1 + examples/Cargo.toml | 2 +- rsocket-benchmark/Cargo.toml | 40 ++++++++++++++++++++++ rsocket-benchmark/benchmark_main.rs | 8 +++++ rsocket-benchmark/benchmarks/fibonaccis.rs | 15 ++++++++ rsocket-benchmark/benchmarks/frames.rs | 19 ++++++++++ rsocket-benchmark/benchmarks/mod.rs | 2 ++ rsocket-messaging/src/lib.rs | 3 -- rsocket-messaging/src/requester.rs | 2 +- rsocket/src/extension/composite.rs | 8 ++--- rsocket/src/extension/mime.rs | 4 +-- rsocket/src/utils.rs | 5 ++- 13 files changed, 97 insertions(+), 16 deletions(-) create mode 100644 rsocket-benchmark/Cargo.toml create mode 100644 rsocket-benchmark/benchmark_main.rs create mode 100644 rsocket-benchmark/benchmarks/fibonaccis.rs create mode 100644 rsocket-benchmark/benchmarks/frames.rs create mode 100644 rsocket-benchmark/benchmarks/mod.rs diff --git a/.gitignore b/.gitignore index 6936990..62518ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ -/target +target/ **/*.rs.bk Cargo.lock + + diff --git a/Cargo.toml b/Cargo.toml index 97b5c80..5c0bb67 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,4 +12,5 @@ members = [ # internal "examples", "rsocket-test", +"rsocket-benchmark", ] diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 390b270..487b36a 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -21,7 +21,7 @@ path = "../rsocket-transport-tcp" path = "../rsocket-transport-websocket" [dev-dependencies.tokio] -version = "0.2.19" +version = "0.2.20" default-features = false features = ["full"] diff --git a/rsocket-benchmark/Cargo.toml b/rsocket-benchmark/Cargo.toml new file mode 100644 index 0000000..c6b70de --- /dev/null +++ b/rsocket-benchmark/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "rsocket_rust_benchmark" +version = "0.0.0" +authors = ["Jeffsky "] +edition = "2018" +publish = false + +[dev-dependencies] +log = "0.4" +futures = "0.3.4" +env_logger = "0.7.1" +bytes = "0.5.4" +hex = "0.4.2" +rand = "0.7.3" +serde = "1.0.106" +serde_derive = "1.0.106" +criterion = "0.3.2" + +[dev-dependencies.rsocket_rust] +path = "../rsocket" +features = ["frame"] + +[dev-dependencies.rsocket_rust_transport_tcp] +path = "../rsocket-transport-tcp" + +[dev-dependencies.rsocket_rust_transport_websocket] +path = "../rsocket-transport-websocket" + +[dev-dependencies.rsocket_rust_messaging] +path = "../rsocket-messaging" + +[dev-dependencies.tokio] +version = "0.2.20" +default-features = false +features = ["full"] + +[[bench]] +name = "bench_main" +path = "benchmark_main.rs" +harness = false \ No newline at end of file diff --git a/rsocket-benchmark/benchmark_main.rs b/rsocket-benchmark/benchmark_main.rs new file mode 100644 index 0000000..3b1b991 --- /dev/null +++ b/rsocket-benchmark/benchmark_main.rs @@ -0,0 +1,8 @@ +use criterion::criterion_main; + +mod benchmarks; + +criterion_main! { + benchmarks::fibonaccis::benches, + benchmarks::frames::benches, +} diff --git a/rsocket-benchmark/benchmarks/fibonaccis.rs b/rsocket-benchmark/benchmarks/fibonaccis.rs new file mode 100644 index 0000000..12b529a --- /dev/null +++ b/rsocket-benchmark/benchmarks/fibonaccis.rs @@ -0,0 +1,15 @@ +use criterion::{black_box, criterion_group, Criterion}; + +fn fibonacci(n: u64) -> u64 { + match n { + 0 => 1, + 1 => 1, + n => fibonacci(n - 1) + fibonacci(n - 2), + } +} + +fn fibonaccis_benchmark(c: &mut Criterion) { + c.bench_function("fib 20", |b| b.iter(|| fibonacci(black_box(20)))); +} + +criterion_group!(benches, fibonaccis_benchmark); diff --git a/rsocket-benchmark/benchmarks/frames.rs b/rsocket-benchmark/benchmarks/frames.rs new file mode 100644 index 0000000..e10a911 --- /dev/null +++ b/rsocket-benchmark/benchmarks/frames.rs @@ -0,0 +1,19 @@ +use bytes::{Bytes, BytesMut}; +use criterion::{criterion_group, Criterion}; +use rsocket_rust::frame::*; +use rsocket_rust::utils::Writeable; + +fn bench_unmarshal_request_response(c: &mut Criterion) { + c.bench_function("unmarshal request_response", |b| { + b.iter(|| { + let f = RequestResponse::builder(1234, 0) + .set_data(Bytes::from("Hello World")) + .set_metadata(Bytes::from("Foobar")) + .build(); + let mut bf = BytesMut::with_capacity(f.len() as usize); + f.write_to(&mut bf); + }) + }); +} + +criterion_group!(benches, bench_unmarshal_request_response); diff --git a/rsocket-benchmark/benchmarks/mod.rs b/rsocket-benchmark/benchmarks/mod.rs new file mode 100644 index 0000000..a5b1bc1 --- /dev/null +++ b/rsocket-benchmark/benchmarks/mod.rs @@ -0,0 +1,2 @@ +pub mod fibonaccis; +pub mod frames; diff --git a/rsocket-messaging/src/lib.rs b/rsocket-messaging/src/lib.rs index 5b8d09f..f57b8f3 100644 --- a/rsocket-messaging/src/lib.rs +++ b/rsocket-messaging/src/lib.rs @@ -1,6 +1,3 @@ -#[macro_use] -extern crate log; - mod misc; mod requester; diff --git a/rsocket-messaging/src/requester.rs b/rsocket-messaging/src/requester.rs index 0c661a7..25e8696 100644 --- a/rsocket-messaging/src/requester.rs +++ b/rsocket-messaging/src/requester.rs @@ -1,5 +1,5 @@ use super::misc::{marshal, unmarshal}; -use bytes::{BufMut, BytesMut}; +use bytes::BytesMut; use rsocket_rust::error::RSocketError; use rsocket_rust::extension::{ CompositeMetadata, MimeType, RoutingMetadata, MIME_APPLICATION_JSON, diff --git a/rsocket/src/extension/composite.rs b/rsocket/src/extension/composite.rs index 1984127..218ad1b 100644 --- a/rsocket/src/extension/composite.rs +++ b/rsocket/src/extension/composite.rs @@ -159,12 +159,10 @@ impl CompositeMetadata { impl CompositeMetadataEntry { pub fn new(mime_type: MimeType, metadata: Bytes) -> CompositeMetadataEntry { - if metadata.len() > U24::max() { - panic!("too large Payload!") - } + assert!(metadata.len() <= (U24::MAX as usize)); CompositeMetadataEntry { - mime_type: mime_type, - metadata: metadata, + mime_type, + metadata, } } diff --git a/rsocket/src/extension/mime.rs b/rsocket/src/extension/mime.rs index 2f6ccca..f50bce0 100644 --- a/rsocket/src/extension/mime.rs +++ b/rsocket/src/extension/mime.rs @@ -35,7 +35,7 @@ impl MimeType { pub fn as_u8(&self) -> Option { match self { - Self::WellKnown(n) => Some(n.clone()), + Self::WellKnown(n) => Some(*n), Self::Normal(_) => None, } } @@ -59,7 +59,7 @@ impl AsRef for MimeType { impl From<&str> for MimeType { fn from(value: &str) -> MimeType { match STR_TO_U8.get(&value) { - Some(v) => Self::WellKnown(v.clone()), + Some(v) => Self::WellKnown(*v), None => Self::Normal(value.to_owned()), } } diff --git a/rsocket/src/utils.rs b/rsocket/src/utils.rs index 62cbd14..6ef9fcf 100644 --- a/rsocket/src/utils.rs +++ b/rsocket/src/utils.rs @@ -20,9 +20,8 @@ pub trait Writeable { pub struct U24; impl U24 { - pub fn max() -> usize { - 0x00FF_FFFF - } + pub const MAX: u32 = 0x00FF_FFFF; + pub const MIN: u32 = 0; pub fn write(n: u32, bf: &mut BytesMut) { bf.put_u8((0xFF & (n >> 16)) as u8); From 9542648d38b81dfbf2ae58ffe6dedf47efdfe5b5 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Sat, 9 May 2020 23:43:52 +0800 Subject: [PATCH 06/70] redesign u24. --- rsocket-messaging/src/builder.rs | 48 +++++ rsocket-messaging/src/lib.rs | 4 +- rsocket-messaging/src/misc.rs | 10 +- rsocket-messaging/src/requester.rs | 98 ++--------- rsocket-test/tests/test_composite_metadata.rs | 5 +- rsocket-test/tests/test_frames.rs | 6 +- rsocket-test/tests/test_messaging.rs | 7 +- rsocket-test/tests/test_mimes.rs | 2 +- rsocket-transport-tcp/src/codec.rs | 6 +- rsocket/src/extension/composite.rs | 10 +- rsocket/src/extension/mime.rs | 166 +++++------------- rsocket/src/extension/mod.rs | 2 +- rsocket/src/extension/routing.rs | 2 +- rsocket/src/frame/lease.rs | 6 +- rsocket/src/frame/mod.rs | 112 ++++++------ rsocket/src/frame/payload.rs | 8 +- rsocket/src/frame/request_channel.rs | 8 +- rsocket/src/frame/request_fnf.rs | 8 +- rsocket/src/frame/request_response.rs | 10 +- rsocket/src/frame/request_stream.rs | 10 +- rsocket/src/frame/setup.rs | 16 +- rsocket/src/frame/utils.rs | 13 +- rsocket/src/transport/fragmentation.rs | 8 +- rsocket/src/transport/socket.rs | 48 ++--- rsocket/src/utils.rs | 93 ++++++++-- 25 files changed, 333 insertions(+), 373 deletions(-) create mode 100644 rsocket-messaging/src/builder.rs diff --git a/rsocket-messaging/src/builder.rs b/rsocket-messaging/src/builder.rs new file mode 100644 index 0000000..c26fcbf --- /dev/null +++ b/rsocket-messaging/src/builder.rs @@ -0,0 +1,48 @@ +use super::requester::Requester; +use rsocket_rust::extension::MimeType; + +pub struct RequesterBuilder { + data_mime_type: MimeType, + route: Option, + data: Option>, +} + +impl Default for RequesterBuilder { + fn default() -> Self { + Self { + data_mime_type: MimeType::APPLICATION_JSON, + route: None, + data: None, + } + } +} + +impl RequesterBuilder { + pub fn data_mime_type(mut self, mime_type: I) -> Self + where + I: Into, + { + self.data_mime_type = mime_type.into(); + self + } + + pub fn setup_route(mut self, route: I) -> Self + where + I: Into, + { + self.route = Some(route.into()); + self + } + + pub fn setup_data(mut self, data: D) -> Self + where + D: Into>, + { + self.data = Some(data.into()); + self + } + + pub fn build(self) -> Requester { + todo!("build requester") + } +} diff --git a/rsocket-messaging/src/lib.rs b/rsocket-messaging/src/lib.rs index f57b8f3..94229a9 100644 --- a/rsocket-messaging/src/lib.rs +++ b/rsocket-messaging/src/lib.rs @@ -1,4 +1,6 @@ +mod builder; mod misc; mod requester; -pub use requester::{RequestSpec, Requester, RequesterBuilder}; +pub use builder::RequesterBuilder; +pub use requester::{RequestSpec, Requester}; diff --git a/rsocket-messaging/src/misc.rs b/rsocket-messaging/src/misc.rs index a8e2bd5..51d8379 100644 --- a/rsocket-messaging/src/misc.rs +++ b/rsocket-messaging/src/misc.rs @@ -1,5 +1,5 @@ use bytes::{BufMut, BytesMut}; -use rsocket_rust::extension::{MimeType, MIME_APPLICATION_CBOR, MIME_APPLICATION_JSON}; +use rsocket_rust::extension::MimeType; use serde::{Deserialize, Serialize}; use std::error::Error; @@ -8,8 +8,8 @@ where T: Deserialize<'a>, { match *mime_type { - MIME_APPLICATION_JSON => Ok(serde_json::from_slice(raw)?), - MIME_APPLICATION_CBOR => Ok(serde_cbor::from_slice(raw)?), + MimeType::APPLICATION_JSON => Ok(serde_json::from_slice(raw)?), + MimeType::APPLICATION_CBOR => Ok(serde_cbor::from_slice(raw)?), _ => panic!(""), } } @@ -23,12 +23,12 @@ where T: Sized + Serialize, { match *mime_type { - MIME_APPLICATION_JSON => { + MimeType::APPLICATION_JSON => { let raw = serde_json::to_vec(data)?; bf.put_slice(&raw[..]); Ok(()) } - MIME_APPLICATION_CBOR => { + MimeType::APPLICATION_CBOR => { let raw = serde_cbor::to_vec(data)?; bf.put_slice(&raw[..]); Ok(()) diff --git a/rsocket-messaging/src/requester.rs b/rsocket-messaging/src/requester.rs index 25e8696..0bd8f47 100644 --- a/rsocket-messaging/src/requester.rs +++ b/rsocket-messaging/src/requester.rs @@ -1,115 +1,51 @@ use super::misc::{marshal, unmarshal}; use bytes::BytesMut; use rsocket_rust::error::RSocketError; -use rsocket_rust::extension::{ - CompositeMetadata, MimeType, RoutingMetadata, MIME_APPLICATION_JSON, - MIME_MESSAGE_X_RSOCKET_ROUTING_V0, -}; +use rsocket_rust::extension::{CompositeMetadata, MimeType, RoutingMetadata}; use rsocket_rust::prelude::*; use rsocket_rust::utils::Writeable; use serde::{Deserialize, Serialize}; use std::collections::LinkedList; use std::error::Error; +use std::sync::Arc; -pub struct RequesterBuilder { - data_mime_type: MimeType, - route: Option, - data: Option>, -} - -impl Default for RequesterBuilder { - fn default() -> Self { - Self { - data_mime_type: MIME_APPLICATION_JSON, - route: None, - data: None, - } - } -} - -impl RequesterBuilder { - pub fn data_mime_type(mut self, mime_type: I) -> Self - where - I: Into, - { - self.data_mime_type = mime_type.into(); - self - } - - pub fn setup_route(mut self, route: I) -> Self - where - I: Into, - { - self.route = Some(route.into()); - self - } - - pub fn setup_data(mut self, data: D) -> Self - where - D: Into>, - { - self.data = Some(data.into()); - self - } - - pub fn build(self) -> Requester - where - S: RSocket + Clone, - { - todo!("build requester") - } +pub struct Requester { + rsocket: Arc>, } -pub struct Requester -where - S: RSocket + Clone, -{ - rsocket: S, -} - -pub struct RequestSpec -where - S: RSocket + Clone, -{ +pub struct RequestSpec { data: Option>, - rsocket: S, + rsocket: Arc>, data_mime_type: MimeType, metadatas: LinkedList<(MimeType, Vec)>, } -impl From for Requester -where - S: RSocket + Clone, -{ - fn from(rsocket: S) -> Requester { - Requester { rsocket } +impl From> for Requester { + fn from(rsocket: Box) -> Requester { + Requester { + rsocket: Arc::new(rsocket), + } } } -impl Requester -where - C: RSocket + Clone, -{ - pub fn route(&self, route: &str) -> RequestSpec { +impl Requester { + pub fn route(&self, route: &str) -> RequestSpec { let routing = RoutingMetadata::builder().push_str(route).build(); let mut buf = BytesMut::new(); routing.write_to(&mut buf); let mut metadatas: LinkedList<(MimeType, Vec)> = Default::default(); - metadatas.push_back((MIME_MESSAGE_X_RSOCKET_ROUTING_V0, buf.to_vec())); + metadatas.push_back((MimeType::MESSAGE_X_RSOCKET_ROUTING_V0, buf.to_vec())); RequestSpec { data: None, rsocket: self.rsocket.clone(), - data_mime_type: MIME_APPLICATION_JSON, + data_mime_type: MimeType::APPLICATION_JSON, metadatas, } } } -impl RequestSpec -where - C: RSocket + Clone, -{ +impl RequestSpec { pub fn metadata(&mut self, metadata: &T, mime_type: M) -> Result<(), Box> where T: Sized + Serialize, @@ -160,7 +96,7 @@ where } #[inline] - fn preflight(self) -> (Payload, MimeType, C) { + fn preflight(self) -> (Payload, MimeType, Arc>) { let mut b = BytesMut::new(); let mut c = CompositeMetadata::builder(); for (mime_type, raw) in self.metadatas.into_iter() { diff --git a/rsocket-test/tests/test_composite_metadata.rs b/rsocket-test/tests/test_composite_metadata.rs index d7ef7df..baf3b04 100644 --- a/rsocket-test/tests/test_composite_metadata.rs +++ b/rsocket-test/tests/test_composite_metadata.rs @@ -6,7 +6,10 @@ use rsocket_rust::utils::Writeable; fn encode_and_decode_composite_metadata() { let bingo = |metadatas: Vec<&CompositeMetadataEntry>| { assert_eq!(2, metadatas.len()); - assert_eq!(extension::MIME_TEXT_PLAIN, *metadatas[0].get_mime_type()); + assert_eq!( + extension::MimeType::TEXT_PLAIN, + *metadatas[0].get_mime_type() + ); assert_eq!("Hello World!", metadatas[0].get_metadata_utf8()); assert_eq!( MimeType::from("application/not_well"), diff --git a/rsocket-test/tests/test_frames.rs b/rsocket-test/tests/test_frames.rs index f4ac4a0..e8b1944 100644 --- a/rsocket-test/tests/test_frames.rs +++ b/rsocket-test/tests/test_frames.rs @@ -20,7 +20,7 @@ fn test_setup() { #[test] fn test_keepalive() { - let f = Keepalive::builder(1234, FLAG_RESPOND) + let f = Keepalive::builder(1234, Frame::FLAG_RESPOND) .set_last_received_position(123) .set_data(Bytes::from("foobar")) .build(); @@ -38,7 +38,7 @@ fn test_request_response() { #[test] fn test_payload() { - let f = Payload::builder(1234, FLAG_NEXT | FLAG_COMPLETE) + let f = Payload::builder(1234, Frame::FLAG_NEXT | Frame::FLAG_COMPLETE) .set_data(Bytes::from("Hello World!")) .set_metadata(Bytes::from("foobar")) .build(); @@ -111,7 +111,7 @@ fn resume_ok() { #[test] fn test_resume() { - let f = Resume::builder(0, FLAG_RESUME) + let f = Resume::builder(0, Frame::FLAG_RESUME) .set_last_received_server_position(123) .set_first_available_client_position(22) .set_token(Bytes::from("this is a token")) diff --git a/rsocket-test/tests/test_messaging.rs b/rsocket-test/tests/test_messaging.rs index f4dcb92..06c3d16 100644 --- a/rsocket-test/tests/test_messaging.rs +++ b/rsocket-test/tests/test_messaging.rs @@ -32,6 +32,8 @@ async fn test_messaging() { .start() .await .expect("Connect failed!"); + + let rsocket: Box = Box::new(rsocket); let requester = Requester::from(rsocket); let post = Student { @@ -52,8 +54,3 @@ async fn test_messaging() { .expect("Empty result!"); println!("------> RESPONSE: {:?}", res); } - -#[test] -fn test_builder() { - RequesterBuilder::default().data_mime_type("application/json"); -} diff --git a/rsocket-test/tests/test_mimes.rs b/rsocket-test/tests/test_mimes.rs index f52509a..f401529 100644 --- a/rsocket-test/tests/test_mimes.rs +++ b/rsocket-test/tests/test_mimes.rs @@ -5,7 +5,7 @@ use rsocket_rust::extension::{self, MimeType}; #[test] fn test_wellknown() { let well = MimeType::from("application/json"); - assert_eq!(extension::MIME_APPLICATION_JSON, well); + assert_eq!(extension::MimeType::APPLICATION_JSON, well); assert_eq!(0x05, well.as_u8().unwrap()); let custom = MimeType::from("application/custom"); assert_eq!(MimeType::Normal("application/custom".to_owned()), custom); diff --git a/rsocket-transport-tcp/src/codec.rs b/rsocket-transport-tcp/src/codec.rs index c240bd6..606a629 100644 --- a/rsocket-transport-tcp/src/codec.rs +++ b/rsocket-transport-tcp/src/codec.rs @@ -1,6 +1,6 @@ use bytes::{Buf, BytesMut}; use rsocket_rust::frame::Frame; -use rsocket_rust::utils::{Writeable, U24}; +use rsocket_rust::utils::{u24, Writeable}; use std::io::{Error, ErrorKind}; use tokio_util::codec::{Decoder, Encoder}; @@ -15,7 +15,7 @@ impl Decoder for LengthBasedFrameCodec { if actual < 3 { return Ok(None); } - let l = U24::read(buf) as usize; + let l = u24::read(buf).into(); if actual < 3 + l { return Ok(None); } @@ -33,7 +33,7 @@ impl Encoder for LengthBasedFrameCodec { fn encode(&mut self, item: Frame, buf: &mut BytesMut) -> Result<(), Self::Error> { let l = item.len(); buf.reserve(3 + l); - U24::write(l as u32, buf); + u24::from(l).write_to(buf); item.write_to(buf); Ok(()) } diff --git a/rsocket/src/extension/composite.rs b/rsocket/src/extension/composite.rs index 218ad1b..e766da7 100644 --- a/rsocket/src/extension/composite.rs +++ b/rsocket/src/extension/composite.rs @@ -1,6 +1,6 @@ use super::mime::MimeType; use crate::error::{ErrorKind, RSocketError}; -use crate::utils::{RSocketResult, Writeable, U24}; +use crate::utils::{u24, RSocketResult, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::collections::LinkedList; use std::convert::TryFrom; @@ -141,7 +141,7 @@ impl CompositeMetadata { "broken composite metadata: not enough bytes!", )); } - let payload_size = U24::read_advance(bs) as usize; + let payload_size = u24::read_advance(bs).into(); if bs.len() < payload_size { return Err(RSocketError::from(format!( "broken composite metadata: require {} bytes!", @@ -159,7 +159,7 @@ impl CompositeMetadata { impl CompositeMetadataEntry { pub fn new(mime_type: MimeType, metadata: Bytes) -> CompositeMetadataEntry { - assert!(metadata.len() <= (U24::MAX as usize)); + assert!(metadata.len() <= (u24::MAX as usize)); CompositeMetadataEntry { mime_type, metadata, @@ -196,8 +196,8 @@ impl Writeable for CompositeMetadataEntry { bf.put_slice(s.as_ref()); } }; - let metadata_len = self.metadata.len() as u32; - U24::write(metadata_len, bf); + let metadata_len = self.metadata.len(); + u24::from(metadata_len).write_to(bf); if metadata_len > 0 { bf.put(self.metadata.bytes()); } diff --git a/rsocket/src/extension/mime.rs b/rsocket/src/extension/mime.rs index f50bce0..0314117 100644 --- a/rsocket/src/extension/mime.rs +++ b/rsocket/src/extension/mime.rs @@ -78,176 +78,94 @@ impl fmt::Display for MimeType { } macro_rules! mime { - ($name:ident,$mime_name:ident, $n:expr,$s:expr) => { + ($name:ident,$n:expr,$s:expr) => { const $name: (u8, &str) = ($n, $s); - pub const $mime_name: MimeType = MimeType::WellKnown($n); + impl MimeType { + pub const $name: Self = Self::WellKnown($n); + } }; } -mime!( - APPLICATION_AVRO, - MIME_APPLICATION_AVRO, - 0x00, - "application/avro" -); -mime!( - APPLICATION_CBOR, - MIME_APPLICATION_CBOR, - 0x01, - "application/avro" -); -mime!( - APPLICATION_GRAPHQL, - MIME_APPLICATION_GRAPHQL, - 0x02, - "application/graphql" -); -mime!( - APPLICATION_GZIP, - MIME_APPLICATION_GZIP, - 0x03, - "application/gzip" -); -mime!( - APPLICATION_JAVASCRIPT, - MIME_APPLICATION_JAVASCRIPT, - 0x04, - "application/javascript" -); -mime!( - APPLICATION_JSON, - MIME_APPLICATION_JSON, - 0x05, - "application/json" -); -mime!( - APPLICATION_OCTET_STREAM, - MIME_APPLICATION_OCTET_STREAM, - 0x06, - "application/octet-stream" -); -mime!( - APPLICATION_PDF, - MIME_APPLICATION_PDF, - 0x07, - "application/pdf" -); +mime!(APPLICATION_AVRO, 0x00, "application/avro"); +mime!(APPLICATION_CBOR, 0x01, "application/avro"); +mime!(APPLICATION_GRAPHQL, 0x02, "application/graphql"); +mime!(APPLICATION_GZIP, 0x03, "application/gzip"); +mime!(APPLICATION_JAVASCRIPT, 0x04, "application/javascript"); +mime!(APPLICATION_JSON, 0x05, "application/json"); +mime!(APPLICATION_OCTET_STREAM, 0x06, "application/octet-stream"); +mime!(APPLICATION_PDF, 0x07, "application/pdf"); mime!( APPLICATION_VND_APACHE_THRIFT_BINARY, - MIME_APPLICATION_VND_APACHE_THRIFT_BINARY, 0x08, "application/vnd.apache.thrift.binary" ); mime!( APPLICATION_VND_GOOGLE_PROTOBUF, - MIME_APPLICATION_VND_GOOGLE_PROTOBUF, 0x09, "application/vnd.google.protobuf" ); -mime!( - APPLICATION_XML, - MIME_APPLICATION_XML, - 0x0A, - "application/xml" -); -mime!( - APPLICATION_ZIP, - MIME_APPLICATION_ZIP, - 0x0B, - "application/zip" -); -mime!(AUDIO_AAC, MIME_AUDIO_AAC, 0x0C, "audio/aac"); -mime!(AUDIO_MP3, MIME_AUDIO_MP3, 0x0D, "audio/mp3"); -mime!(AUDIO_MP4, MIME_AUDIO_MP4, 0x0E, "audio/mp4"); -mime!(AUDIO_MPEG3, MIME_AUDIO_MPEG3, 0x0F, "audio/mpeg3"); -mime!(AUDIO_MPEG, MIME_AUDIO_MPEG, 0x10, "audio/mpeg"); -mime!(AUDIO_OGG, MIME_AUDIO_OGG, 0x11, "audio/ogg"); -mime!(AUDIO_OPUS, MIME_AUDIO_OPUS, 0x12, "audio/opus"); -mime!(AUDIO_VORBIS, MIME_AUDIO_VORBIS, 0x13, "audio/vorbis"); -mime!(IMAGE_BMP, MIME_IMAGE_BMP, 0x14, "image/bmp"); -mime!(IMAGE_GIF, MIME_IMAGE_GIF, 0x15, "image/gif"); -mime!( - IMAGE_HEIC_SEQUENCE, - MIME_IMAGE_HEIC_SEQUENCE, - 0x16, - "image/heic-sequence" -); -mime!(IMAGE_HEIC, MIME_IMAGE_HEIC, 0x17, "image/heic"); -mime!( - IMAGE_HEIF_SEQUENCE, - MIME_IMAGE_HEIF_SEQUENCE, - 0x18, - "image/heif-sequence" -); -mime!(IMAGE_HEIF, MIME_IMAGE_HEIF, 0x19, "image/heif"); -mime!(IMAGE_JPEG, MIME_IMAGE_JPEG, 0x1A, "image/jpeg"); -mime!(IMAGE_PNG, MIME_IMAGE_PNG, 0x1B, "image/png"); -mime!(IMAGE_TIFF, MIME_IMAGE_TIFF, 0x1C, "image/tiff"); -mime!( - MULTIPART_MIXED, - MIME_MULTIPART_MIXED, - 0x1D, - "multipart/mixed" -); -mime!(TEXT_CSS, MIME_TEXT_CSS, 0x1E, "text/css"); -mime!(TEXT_CSV, MIME_TEXT_CSV, 0x1F, "text/csv"); -mime!(TEXT_HTML, MIME_TEXT_HTML, 0x20, "text/html"); -mime!(TEXT_PLAIN, MIME_TEXT_PLAIN, 0x21, "text/plain"); -mime!(TEXT_XML, MIME_TEXT_XML, 0x22, "text/xml"); -mime!(VIDEO_H264, MIME_VIDEO_H264, 0x23, "video/H264"); -mime!(VIDEO_H265, MIME_VIDEO_H265, 0x24, "video/H265"); -mime!(VIDEO_VP8, MIME_VIDEO_VP8, 0x25, "video/VP8"); -mime!( - APPLICATION_X_HESSIAN, - MIME_APPLICATION_X_HESSIAN, - 0x26, - "application/x-hessian" -); -mime!( - APPLICATION_X_JAVA_OBJECT, - MIME_APPLICATION_X_JAVA_OBJECT, - 0x27, - "application/x-java-object" -); +mime!(APPLICATION_XML, 0x0A, "application/xml"); +mime!(APPLICATION_ZIP, 0x0B, "application/zip"); +mime!(AUDIO_AAC, 0x0C, "audio/aac"); +mime!(AUDIO_MP3, 0x0D, "audio/mp3"); +mime!(AUDIO_MP4, 0x0E, "audio/mp4"); +mime!(AUDIO_MPEG3, 0x0F, "audio/mpeg3"); +mime!(AUDIO_MPEG, 0x10, "audio/mpeg"); +mime!(AUDIO_OGG, 0x11, "audio/ogg"); +mime!(AUDIO_OPUS, 0x12, "audio/opus"); +mime!(AUDIO_VORBIS, 0x13, "audio/vorbis"); +mime!(IMAGE_BMP, 0x14, "image/bmp"); +mime!(IMAGE_GIF, 0x15, "image/gif"); +mime!(IMAGE_HEIC_SEQUENCE, 0x16, "image/heic-sequence"); +mime!(IMAGE_HEIC, 0x17, "image/heic"); +mime!(IMAGE_HEIF_SEQUENCE, 0x18, "image/heif-sequence"); +mime!(IMAGE_HEIF, 0x19, "image/heif"); +mime!(IMAGE_JPEG, 0x1A, "image/jpeg"); +mime!(IMAGE_PNG, 0x1B, "image/png"); +mime!(IMAGE_TIFF, 0x1C, "image/tiff"); +mime!(MULTIPART_MIXED, 0x1D, "multipart/mixed"); +mime!(TEXT_CSS, 0x1E, "text/css"); +mime!(TEXT_CSV, 0x1F, "text/csv"); +mime!(TEXT_HTML, 0x20, "text/html"); +mime!(TEXT_PLAIN, 0x21, "text/plain"); +mime!(TEXT_XML, 0x22, "text/xml"); +mime!(VIDEO_H264, 0x23, "video/H264"); +mime!(VIDEO_H265, 0x24, "video/H265"); +mime!(VIDEO_VP8, 0x25, "video/VP8"); +mime!(APPLICATION_X_HESSIAN, 0x26, "application/x-hessian"); +mime!(APPLICATION_X_JAVA_OBJECT, 0x27, "application/x-java-object"); mime!( APPLICATION_CLOUDEVENTS_JSON, - MIME_APPLICATION_CLOUDEVENTS_JSON, 0x28, "application/cloudevents+json" ); mime!( MESSAGE_X_RSOCKET_MIME_TYPE_V0, - MIME_MESSAGE_X_RSOCKET_MIME_TYPE_V0, 0x7A, "message/x.rsocket.mime-type.v0" ); mime!( MESSAGE_X_RSOCKET_ACCEPT_TIME_TYPES_V0, - MIME_MESSAGE_X_RSOCKET_ACCEPT_TIME_TYPES_V0, 0x7B, "message/x.rsocket.accept-mime-types.v0" ); mime!( MESSAGE_X_RSOCKET_AUTHENTICATION_V0, - MIME_MESSAGE_X_RSOCKET_AUTHENTICATION_V0, 0x7C, "message/x.rsocket.authentication.v0" ); mime!( MESSAGE_X_RSOCKET_TRACING_ZIPKIN_V0, - MIME_MESSAGE_X_RSOCKET_TRACING_ZIPKIN_V0, 0x7D, "message/x.rsocket.tracing-zipkin.v0" ); mime!( MESSAGE_X_RSOCKET_ROUTING_V0, - MIME_MESSAGE_X_RSOCKET_ROUTING_V0, 0x7E, "message/x.rsocket.routing.v0" ); mime!( MESSAGE_X_RSOCKET_COMPOSITE_METADATA_V0, - MIME_MESSAGE_X_RSOCKET_COMPOSITE_METADATA_V0, 0x7F, "message/x.rsocket.composite-metadata.v0" ); diff --git a/rsocket/src/extension/mod.rs b/rsocket/src/extension/mod.rs index df8bf80..27a528f 100644 --- a/rsocket/src/extension/mod.rs +++ b/rsocket/src/extension/mod.rs @@ -3,5 +3,5 @@ mod mime; mod routing; pub use composite::{CompositeMetadata, CompositeMetadataBuilder, CompositeMetadataEntry}; -pub use mime::*; +pub use mime::MimeType; pub use routing::{RoutingMetadata, RoutingMetadataBuilder}; diff --git a/rsocket/src/extension/routing.rs b/rsocket/src/extension/routing.rs index ca1e150..30cc349 100644 --- a/rsocket/src/extension/routing.rs +++ b/rsocket/src/extension/routing.rs @@ -1,5 +1,5 @@ use crate::error::{ErrorKind, RSocketError}; -use crate::utils::{RSocketResult, Writeable, U24}; +use crate::utils::{RSocketResult, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; const MAX_ROUTING_TAG_LEN: usize = 0xFF; diff --git a/rsocket/src/frame/lease.rs b/rsocket/src/frame/lease.rs index fe4f7d6..e3fce69 100644 --- a/rsocket/src/frame/lease.rs +++ b/rsocket/src/frame/lease.rs @@ -1,4 +1,4 @@ -use super::{Body, Frame, FLAG_METADATA}; +use super::{Body, Frame}; use crate::utils::{RSocketResult, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -30,7 +30,7 @@ impl LeaseBuilder { pub fn set_metadata(mut self, metadata: Bytes) -> Self { self.value.metadata = Some(metadata); - self.flag |= FLAG_METADATA; + self.flag |= Frame::FLAG_METADATA; self } @@ -53,7 +53,7 @@ impl Lease { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { let ttl = bf.get_u32(); let n = bf.get_u32(); - let m = if flag & FLAG_METADATA != 0 { + let m = if flag & Frame::FLAG_METADATA != 0 { Some(bf.to_bytes()) } else { None diff --git a/rsocket/src/frame/mod.rs b/rsocket/src/frame/mod.rs index a28d1ee..515d9a5 100644 --- a/rsocket/src/frame/mod.rs +++ b/rsocket/src/frame/mod.rs @@ -36,30 +36,6 @@ pub use setup::{Setup, SetupBuilder}; pub use utils::*; pub use version::Version; -pub const FLAG_NEXT: u16 = 0x01 << 5; -pub const FLAG_COMPLETE: u16 = 0x01 << 6; -pub const FLAG_FOLLOW: u16 = 0x01 << 7; -pub const FLAG_METADATA: u16 = 0x01 << 8; -pub const FLAG_IGNORE: u16 = 0x01 << 9; -pub const FLAG_LEASE: u16 = FLAG_COMPLETE; -pub const FLAG_RESUME: u16 = FLAG_FOLLOW; -pub const FLAG_RESPOND: u16 = FLAG_FOLLOW; - -pub const TYPE_SETUP: u16 = 0x01; -pub const TYPE_LEASE: u16 = 0x02; -pub const TYPE_KEEPALIVE: u16 = 0x03; -pub const TYPE_REQUEST_RESPONSE: u16 = 0x04; -pub const TYPE_REQUEST_FNF: u16 = 0x05; -pub const TYPE_REQUEST_STREAM: u16 = 0x06; -pub const TYPE_REQUEST_CHANNEL: u16 = 0x07; -pub const TYPE_REQUEST_N: u16 = 0x08; -pub const TYPE_CANCEL: u16 = 0x09; -pub const TYPE_PAYLOAD: u16 = 0x0A; -pub const TYPE_ERROR: u16 = 0x0B; -pub const TYPE_METADATA_PUSH: u16 = 0x0C; -pub const TYPE_RESUME: u16 = 0x0D; -pub const TYPE_RESUME_OK: u16 = 0x0E; - pub const REQUEST_MAX: u32 = 0x7FFF_FFFF; // 2147483647 pub(crate) const LEN_HEADER: usize = 6; @@ -89,6 +65,32 @@ pub struct Frame { pub(crate) flag: u16, } +impl Frame { + pub const FLAG_NEXT: u16 = 0x01 << 5; + pub const FLAG_COMPLETE: u16 = 0x01 << 6; + pub const FLAG_FOLLOW: u16 = 0x01 << 7; + pub const FLAG_METADATA: u16 = 0x01 << 8; + pub const FLAG_IGNORE: u16 = 0x01 << 9; + pub const FLAG_LEASE: u16 = Self::FLAG_COMPLETE; + pub const FLAG_RESUME: u16 = Self::FLAG_FOLLOW; + pub const FLAG_RESPOND: u16 = Self::FLAG_FOLLOW; + + pub const TYPE_SETUP: u16 = 0x01; + pub const TYPE_LEASE: u16 = 0x02; + pub const TYPE_KEEPALIVE: u16 = 0x03; + pub const TYPE_REQUEST_RESPONSE: u16 = 0x04; + pub const TYPE_REQUEST_FNF: u16 = 0x05; + pub const TYPE_REQUEST_STREAM: u16 = 0x06; + pub const TYPE_REQUEST_CHANNEL: u16 = 0x07; + pub const TYPE_REQUEST_N: u16 = 0x08; + pub const TYPE_CANCEL: u16 = 0x09; + pub const TYPE_PAYLOAD: u16 = 0x0A; + pub const TYPE_ERROR: u16 = 0x0B; + pub const TYPE_METADATA_PUSH: u16 = 0x0C; + pub const TYPE_RESUME: u16 = 0x0D; + pub const TYPE_RESUME_OK: u16 = 0x0E; +} + impl Writeable for Frame { fn write_to(&self, bf: &mut BytesMut) { bf.put_u32(self.stream_id); @@ -148,20 +150,22 @@ impl Frame { let n = b.get_u16(); let (flag, kind) = (n & 0x03FF, (n & 0xFC00) >> 10); let body = match kind { - TYPE_SETUP => Setup::decode(flag, b).map(Body::Setup), - TYPE_REQUEST_RESPONSE => RequestResponse::decode(flag, b).map(Body::RequestResponse), - TYPE_REQUEST_STREAM => RequestStream::decode(flag, b).map(Body::RequestStream), - TYPE_REQUEST_CHANNEL => RequestChannel::decode(flag, b).map(Body::RequestChannel), - TYPE_REQUEST_FNF => RequestFNF::decode(flag, b).map(Body::RequestFNF), - TYPE_REQUEST_N => RequestN::decode(flag, b).map(Body::RequestN), - TYPE_METADATA_PUSH => MetadataPush::decode(flag, b).map(Body::MetadataPush), - TYPE_KEEPALIVE => Keepalive::decode(flag, b).map(Body::Keepalive), - TYPE_PAYLOAD => Payload::decode(flag, b).map(Body::Payload), - TYPE_LEASE => Lease::decode(flag, b).map(Body::Lease), - TYPE_CANCEL => Ok(Body::Cancel()), - TYPE_ERROR => Error::decode(flag, b).map(Body::Error), - TYPE_RESUME_OK => ResumeOK::decode(flag, b).map(Body::ResumeOK), - TYPE_RESUME => Resume::decode(flag, b).map(Body::Resume), + Self::TYPE_SETUP => Setup::decode(flag, b).map(Body::Setup), + Self::TYPE_REQUEST_RESPONSE => { + RequestResponse::decode(flag, b).map(Body::RequestResponse) + } + Self::TYPE_REQUEST_STREAM => RequestStream::decode(flag, b).map(Body::RequestStream), + Self::TYPE_REQUEST_CHANNEL => RequestChannel::decode(flag, b).map(Body::RequestChannel), + Self::TYPE_REQUEST_FNF => RequestFNF::decode(flag, b).map(Body::RequestFNF), + Self::TYPE_REQUEST_N => RequestN::decode(flag, b).map(Body::RequestN), + Self::TYPE_METADATA_PUSH => MetadataPush::decode(flag, b).map(Body::MetadataPush), + Self::TYPE_KEEPALIVE => Keepalive::decode(flag, b).map(Body::Keepalive), + Self::TYPE_PAYLOAD => Payload::decode(flag, b).map(Body::Payload), + Self::TYPE_LEASE => Lease::decode(flag, b).map(Body::Lease), + Self::TYPE_CANCEL => Ok(Body::Cancel()), + Self::TYPE_ERROR => Error::decode(flag, b).map(Body::Error), + Self::TYPE_RESUME_OK => ResumeOK::decode(flag, b).map(Body::ResumeOK), + Self::TYPE_RESUME => Resume::decode(flag, b).map(Body::Resume), _ => Err(RSocketError::from(format!("illegal frame type: {}", kind))), }; body.map(|it| Frame::new(sid, it, flag)) @@ -191,30 +195,30 @@ impl Frame { } pub fn has_next(&self) -> bool { - self.flag & FLAG_NEXT != 0 + self.flag & Self::FLAG_NEXT != 0 } pub fn has_complete(&self) -> bool { - self.flag & FLAG_COMPLETE != 0 + self.flag & Self::FLAG_COMPLETE != 0 } } #[inline] fn to_frame_type(body: &Body) -> u16 { match body { - Body::Setup(_) => TYPE_SETUP, - Body::Lease(_) => TYPE_LEASE, - Body::Keepalive(_) => TYPE_KEEPALIVE, - Body::RequestResponse(_) => TYPE_REQUEST_RESPONSE, - Body::RequestFNF(_) => TYPE_REQUEST_FNF, - Body::RequestStream(_) => TYPE_REQUEST_STREAM, - Body::RequestChannel(_) => TYPE_REQUEST_CHANNEL, - Body::RequestN(_) => TYPE_REQUEST_N, - Body::Cancel() => TYPE_CANCEL, - Body::Payload(_) => TYPE_PAYLOAD, - Body::Error(_) => TYPE_ERROR, - Body::MetadataPush(_) => TYPE_METADATA_PUSH, - Body::Resume(_) => TYPE_RESUME, - Body::ResumeOK(_) => TYPE_RESUME_OK, + Body::Setup(_) => Frame::TYPE_SETUP, + Body::Lease(_) => Frame::TYPE_LEASE, + Body::Keepalive(_) => Frame::TYPE_KEEPALIVE, + Body::RequestResponse(_) => Frame::TYPE_REQUEST_RESPONSE, + Body::RequestFNF(_) => Frame::TYPE_REQUEST_FNF, + Body::RequestStream(_) => Frame::TYPE_REQUEST_STREAM, + Body::RequestChannel(_) => Frame::TYPE_REQUEST_CHANNEL, + Body::RequestN(_) => Frame::TYPE_REQUEST_N, + Body::Cancel() => Frame::TYPE_CANCEL, + Body::Payload(_) => Frame::TYPE_PAYLOAD, + Body::Error(_) => Frame::TYPE_ERROR, + Body::MetadataPush(_) => Frame::TYPE_METADATA_PUSH, + Body::Resume(_) => Frame::TYPE_RESUME, + Body::ResumeOK(_) => Frame::TYPE_RESUME_OK, } } diff --git a/rsocket/src/frame/payload.rs b/rsocket/src/frame/payload.rs index 9c44d65..22adfa5 100644 --- a/rsocket/src/frame/payload.rs +++ b/rsocket/src/frame/payload.rs @@ -1,4 +1,4 @@ -use super::{Body, Frame, PayloadSupport, FLAG_METADATA}; +use super::{Body, Frame, PayloadSupport}; use crate::utils::{RSocketResult, Writeable}; use bytes::{BufMut, Bytes, BytesMut}; @@ -31,11 +31,11 @@ impl PayloadBuilder { match data_and_metadata.1 { Some(m) => { self.value.metadata = Some(m); - self.flag |= FLAG_METADATA; + self.flag |= Frame::FLAG_METADATA; } None => { self.value.metadata = None; - self.flag &= !FLAG_METADATA; + self.flag &= !Frame::FLAG_METADATA; } } self @@ -48,7 +48,7 @@ impl PayloadBuilder { pub fn set_metadata(mut self, metadata: Bytes) -> Self { self.value.metadata = Some(metadata); - self.flag |= FLAG_METADATA; + self.flag |= Frame::FLAG_METADATA; self } diff --git a/rsocket/src/frame/request_channel.rs b/rsocket/src/frame/request_channel.rs index 7b5de50..0244bc1 100644 --- a/rsocket/src/frame/request_channel.rs +++ b/rsocket/src/frame/request_channel.rs @@ -1,4 +1,4 @@ -use super::{Body, Frame, PayloadSupport, FLAG_METADATA, REQUEST_MAX}; +use super::{Body, Frame, PayloadSupport, REQUEST_MAX}; use crate::utils::{RSocketResult, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -42,11 +42,11 @@ impl RequestChannelBuilder { match data_and_metadata.1 { Some(m) => { self.value.metadata = Some(m); - self.flag |= FLAG_METADATA; + self.flag |= Frame::FLAG_METADATA; } None => { self.value.metadata = None; - self.flag &= !FLAG_METADATA; + self.flag &= !Frame::FLAG_METADATA; } } self @@ -54,7 +54,7 @@ impl RequestChannelBuilder { pub fn set_metadata(mut self, metadata: Bytes) -> Self { self.value.metadata = Some(metadata); - self.flag |= FLAG_METADATA; + self.flag |= Frame::FLAG_METADATA; self } diff --git a/rsocket/src/frame/request_fnf.rs b/rsocket/src/frame/request_fnf.rs index f1d5817..f88d2b4 100644 --- a/rsocket/src/frame/request_fnf.rs +++ b/rsocket/src/frame/request_fnf.rs @@ -1,4 +1,4 @@ -use super::{Body, Frame, PayloadSupport, FLAG_METADATA}; +use super::{Body, Frame, PayloadSupport}; use crate::utils::{RSocketResult, Writeable}; use bytes::{BufMut, Bytes, BytesMut}; @@ -32,7 +32,7 @@ impl RequestFNFBuilder { pub fn set_metadata(mut self, metadata: Bytes) -> Self { self.value.metadata = Some(metadata); - self.flag |= FLAG_METADATA; + self.flag |= Frame::FLAG_METADATA; self } @@ -46,11 +46,11 @@ impl RequestFNFBuilder { match data_and_metadata.1 { Some(m) => { self.value.metadata = Some(m); - self.flag |= FLAG_METADATA; + self.flag |= Frame::FLAG_METADATA; } None => { self.value.metadata = None; - self.flag &= !FLAG_METADATA; + self.flag &= !Frame::FLAG_METADATA; } } self diff --git a/rsocket/src/frame/request_response.rs b/rsocket/src/frame/request_response.rs index b4c0da4..1e8eb0a 100644 --- a/rsocket/src/frame/request_response.rs +++ b/rsocket/src/frame/request_response.rs @@ -1,5 +1,5 @@ -use super::{Body, Frame, PayloadSupport, FLAG_METADATA}; -use crate::utils::{RSocketResult, Writeable, U24}; +use super::{Body, Frame, PayloadSupport}; +use crate::utils::{RSocketResult, Writeable}; use bytes::{BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] @@ -31,11 +31,11 @@ impl RequestResponseBuilder { match data_and_metadata.1 { Some(m) => { self.value.metadata = Some(m); - self.flag |= FLAG_METADATA; + self.flag |= Frame::FLAG_METADATA; } None => { self.value.metadata = None; - self.flag &= !FLAG_METADATA; + self.flag &= !Frame::FLAG_METADATA; } } self @@ -43,7 +43,7 @@ impl RequestResponseBuilder { pub fn set_metadata(mut self, metadata: Bytes) -> Self { self.value.metadata = Some(metadata); - self.flag |= FLAG_METADATA; + self.flag |= Frame::FLAG_METADATA; self } diff --git a/rsocket/src/frame/request_stream.rs b/rsocket/src/frame/request_stream.rs index 9576f6b..9b2dd1a 100644 --- a/rsocket/src/frame/request_stream.rs +++ b/rsocket/src/frame/request_stream.rs @@ -1,5 +1,5 @@ -use super::{Body, Frame, PayloadSupport, FLAG_METADATA, REQUEST_MAX}; -use crate::utils::{RSocketResult, Writeable, U24}; +use super::{Body, Frame, PayloadSupport, REQUEST_MAX}; +use crate::utils::{RSocketResult, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] @@ -30,11 +30,11 @@ impl RequestStreamBuilder { match data_and_metadata.1 { Some(m) => { self.value.metadata = Some(m); - self.flag |= FLAG_METADATA; + self.flag |= Frame::FLAG_METADATA; } None => { self.value.metadata = None; - self.flag &= !FLAG_METADATA; + self.flag &= !Frame::FLAG_METADATA; } } self @@ -47,7 +47,7 @@ impl RequestStreamBuilder { pub fn set_metadata(mut self, metadata: Bytes) -> Self { self.value.metadata = Some(metadata); - self.flag |= FLAG_METADATA; + self.flag |= Frame::FLAG_METADATA; self } } diff --git a/rsocket/src/frame/setup.rs b/rsocket/src/frame/setup.rs index a16919c..f1e0975 100644 --- a/rsocket/src/frame/setup.rs +++ b/rsocket/src/frame/setup.rs @@ -1,4 +1,4 @@ -use super::{Body, Frame, PayloadSupport, Version, FLAG_METADATA, FLAG_RESUME}; +use super::{Body, Frame, PayloadSupport, Version}; use crate::utils::{RSocketResult, Writeable, DEFAULT_MIME_TYPE}; use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::time::Duration; @@ -27,7 +27,7 @@ impl Setup { let minor = b.get_u16(); let keepalive = b.get_u32(); let lifetime = b.get_u32(); - let token: Option = if flag & FLAG_RESUME != 0 { + let token: Option = if flag & Frame::FLAG_RESUME != 0 { let l = b.get_u16(); Some(b.split_to(l as usize).freeze()) } else { @@ -158,7 +158,7 @@ impl SetupBuilder { } pub fn set_metadata(mut self, bs: Bytes) -> Self { - self.flag |= FLAG_METADATA; + self.flag |= Frame::FLAG_METADATA; self.value.metadata = Some(bs); self } @@ -180,7 +180,7 @@ impl SetupBuilder { pub fn set_token(mut self, token: Bytes) -> Self { self.value.token = Some(token); - self.flag |= FLAG_RESUME; + self.flag |= Frame::FLAG_RESUME; self } @@ -189,9 +189,7 @@ impl SetupBuilder { I: Into, { let mime = mime.into(); - if mime.len() > 256 { - panic!("maximum mime length is 256"); - } + assert!(mime.len() <= 256); self.value.mime_metadata = Bytes::from(mime); self } @@ -201,9 +199,7 @@ impl SetupBuilder { I: Into, { let mime = mime.into(); - if mime.len() > 256 { - panic!("maximum mime length is 256"); - } + assert!(mime.len() <= 256); self.value.mime_data = Bytes::from(mime); self } diff --git a/rsocket/src/frame/utils.rs b/rsocket/src/frame/utils.rs index 7f6e818..7e4d38b 100644 --- a/rsocket/src/frame/utils.rs +++ b/rsocket/src/frame/utils.rs @@ -1,5 +1,5 @@ -use super::FLAG_METADATA; -use crate::utils::U24; +use super::Frame; +use crate::utils::{u24, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; pub(crate) struct PayloadSupport {} @@ -18,9 +18,9 @@ impl PayloadSupport { } pub fn read(flag: u16, bf: &mut BytesMut) -> (Option, Option) { - let m: Option = if flag & FLAG_METADATA != 0 { - let n = U24::read_advance(bf); - Some(bf.split_to(n as usize).freeze()) + let m: Option = if flag & Frame::FLAG_METADATA != 0 { + let n = u24::read_advance(bf); + Some(bf.split_to(n.into()).freeze()) } else { None }; @@ -34,8 +34,7 @@ impl PayloadSupport { pub fn write(bf: &mut BytesMut, metadata: Option<&Bytes>, data: Option<&Bytes>) { if let Some(v) = metadata { - let n = v.len() as u32; - U24::write(n, bf); + u24::from(v.len()).write_to(bf); bf.put(v.clone()); } if let Some(v) = data { diff --git a/rsocket/src/transport/fragmentation.rs b/rsocket/src/transport/fragmentation.rs index fdbcf4a..e319497 100644 --- a/rsocket/src/transport/fragmentation.rs +++ b/rsocket/src/transport/fragmentation.rs @@ -123,7 +123,7 @@ impl Joiner { } pub(crate) fn get_flag(&self) -> u16 { - self.first().get_flag() & !frame::FLAG_FOLLOW + self.first().get_flag() & !Frame::FLAG_FOLLOW } pub(crate) fn first(&self) -> &Frame { @@ -138,14 +138,14 @@ impl Joiner { #[cfg(test)] mod tests { - use crate::frame; + use crate::frame::{self, Frame}; use crate::payload::Payload; use crate::transport::{Joiner, Splitter}; use bytes::{Buf, Bytes}; #[test] fn test_joiner() { - let first = frame::Payload::builder(1, frame::FLAG_FOLLOW) + let first = frame::Payload::builder(1, Frame::FLAG_FOLLOW) .set_data(Bytes::from("(ROOT)")) .set_metadata(Bytes::from("(ROOT)")) .build(); @@ -153,7 +153,7 @@ mod tests { joiner.push(first); for i in 0..10 { - let flag = if i == 9 { 0u16 } else { frame::FLAG_FOLLOW }; + let flag = if i == 9 { 0u16 } else { Frame::FLAG_FOLLOW }; let next = frame::Payload::builder(1, flag) .set_data(Bytes::from(format!("(data{:04})", i))) .set_metadata(Bytes::from(format!("(data{:04})", i))) diff --git a/rsocket/src/transport/socket.rs b/rsocket/src/transport/socket.rs index 0759a1a..274c9dd 100644 --- a/rsocket/src/transport/socket.rs +++ b/rsocket/src/transport/socket.rs @@ -192,7 +192,7 @@ where self.on_payload(sid, flag, input).await; } Body::Keepalive(v) => { - if flag & frame::FLAG_RESPOND != 0 { + if flag & Frame::FLAG_RESPOND != 0 { debug!("got keepalive: {:?}", v); self.on_keepalive(v).await; } @@ -230,7 +230,7 @@ where let sid = input.get_stream_id(); let mut joiners = self.joiners.lock().await; - if input.get_flag() & frame::FLAG_FOLLOW != 0 { + if input.get_flag() & Frame::FLAG_FOLLOW != 0 { // TODO: check conflict (*joiners) .entry(sid) @@ -359,23 +359,23 @@ where }, Handler::ResRR(c) => unreachable!(), Handler::ReqRS(sender) => { - if flag & frame::FLAG_NEXT != 0 { + if flag & Frame::FLAG_NEXT != 0 { sender .unbounded_send(Ok(input)) .expect("Send payload response failed."); } - if flag & frame::FLAG_COMPLETE != 0 { + if flag & Frame::FLAG_COMPLETE != 0 { o.remove(); } } Handler::ReqRC(sender) => { // TODO: support channel - if flag & frame::FLAG_NEXT != 0 { + if flag & Frame::FLAG_NEXT != 0 { sender .unbounded_send(Ok(input)) .expect("Send payload response failed"); } - if flag & frame::FLAG_COMPLETE != 0 { + if flag & Frame::FLAG_COMPLETE != 0 { o.remove(); } } @@ -446,7 +446,7 @@ where &tx, sid, res, - frame::FLAG_NEXT | frame::FLAG_COMPLETE, + Frame::FLAG_NEXT | Frame::FLAG_COMPLETE, ); } Err(e) => { @@ -473,7 +473,7 @@ where while let Some(next) = payloads.next().await { match next { Ok(it) => { - Self::try_send_payload(&splitter, &tx, sid, it, frame::FLAG_NEXT); + Self::try_send_payload(&splitter, &tx, sid, it, Frame::FLAG_NEXT); } Err(e) => { let sending = frame::Error::builder(sid, 0) @@ -485,7 +485,7 @@ where } }; } - let complete = frame::Payload::builder(sid, frame::FLAG_COMPLETE).build(); + let complete = frame::Payload::builder(sid, Frame::FLAG_COMPLETE).build(); tx.unbounded_send(complete) .expect("Send stream complete response failed"); }); @@ -512,7 +512,7 @@ where let sending = match next { Ok(v) => { let (d, m) = v.split(); - let mut bu = frame::Payload::builder(sid, frame::FLAG_NEXT); + let mut bu = frame::Payload::builder(sid, Frame::FLAG_NEXT); if let Some(b) = d { bu = bu.set_data(b); } @@ -528,7 +528,7 @@ where }; tx.unbounded_send(sending).unwrap(); } - let complete = frame::Payload::builder(sid, frame::FLAG_COMPLETE).build(); + let complete = frame::Payload::builder(sid, Frame::FLAG_COMPLETE).build(); if let Err(e) = tx.unbounded_send(complete) { error!("complete REQUEST_CHANNEL failed: {}", e); } @@ -569,11 +569,11 @@ where for next in sp.cut(res, 4) { if let Some(cur) = prev.take() { let sending = if cuts == 1 { - frame::RequestChannel::builder(sid, flag | frame::FLAG_FOLLOW) + frame::RequestChannel::builder(sid, flag | Frame::FLAG_FOLLOW) .set_all(cur.split()) .build() } else { - frame::Payload::builder(sid, frame::FLAG_FOLLOW) + frame::Payload::builder(sid, Frame::FLAG_FOLLOW) .set_all(cur.split()) .build() }; @@ -629,11 +629,11 @@ where for next in sp.cut(res, 0) { if let Some(cur) = prev.take() { let sending = if cuts == 1 { - frame::Payload::builder(sid, flag | frame::FLAG_FOLLOW) + frame::Payload::builder(sid, flag | Frame::FLAG_FOLLOW) .set_all(cur.split()) .build() } else { - frame::Payload::builder(sid, frame::FLAG_FOLLOW) + frame::Payload::builder(sid, Frame::FLAG_FOLLOW) .set_all(cur.split()) .build() }; @@ -702,12 +702,12 @@ where if let Some(cur) = prev.take() { let sending = if cuts == 1 { // make first frame as request_fnf. - frame::RequestFNF::builder(sid, frame::FLAG_FOLLOW) + frame::RequestFNF::builder(sid, Frame::FLAG_FOLLOW) .set_all(cur.split()) .build() } else { // make other frames as payload. - frame::Payload::builder(sid, frame::FLAG_FOLLOW) + frame::Payload::builder(sid, Frame::FLAG_FOLLOW) .set_all(cur.split()) .build() }; @@ -772,12 +772,12 @@ where if let Some(cur) = prev.take() { let sending = if cuts == 1 { // make first frame as request_response. - frame::RequestResponse::builder(sid, frame::FLAG_FOLLOW) + frame::RequestResponse::builder(sid, Frame::FLAG_FOLLOW) .set_all(cur.split()) .build() } else { // make other frames as payload. - frame::Payload::builder(sid, frame::FLAG_FOLLOW) + frame::Payload::builder(sid, Frame::FLAG_FOLLOW) .set_all(cur.split()) .build() }; @@ -848,12 +848,12 @@ where if let Some(cur) = prev.take() { let sending: Frame = if cuts == 1 { // make first frame as request_stream. - frame::RequestStream::builder(sid, frame::FLAG_FOLLOW) + frame::RequestStream::builder(sid, Frame::FLAG_FOLLOW) .set_all(cur.split()) .build() } else { // make other frames as payload. - frame::Payload::builder(sid, frame::FLAG_FOLLOW) + frame::Payload::builder(sid, Frame::FLAG_FOLLOW) .set_all(cur.split()) .build() }; @@ -917,9 +917,9 @@ where Ok(it) => { if first { first = false; - Self::try_send_channel(&splitter, &tx, sid, it, frame::FLAG_NEXT) + Self::try_send_channel(&splitter, &tx, sid, it, Frame::FLAG_NEXT) } else { - Self::try_send_payload(&splitter, &tx, sid, it, frame::FLAG_NEXT) + Self::try_send_payload(&splitter, &tx, sid, it, Frame::FLAG_NEXT) } } Err(e) => { @@ -933,7 +933,7 @@ where } }; } - let sending = frame::Payload::builder(sid, frame::FLAG_COMPLETE).build(); + let sending = frame::Payload::builder(sid, Frame::FLAG_COMPLETE).build(); if let Err(e) = tx.unbounded_send(sending) { error!("complete REQUEST_CHANNEL failed: {}", e); } diff --git a/rsocket/src/utils.rs b/rsocket/src/utils.rs index 6ef9fcf..8d06dfb 100644 --- a/rsocket/src/utils.rs +++ b/rsocket/src/utils.rs @@ -17,32 +17,89 @@ pub trait Writeable { } } -pub struct U24; +#[allow(non_camel_case_types)] +#[derive(Default, Clone, Copy, Debug)] +pub struct u24(u32); -impl U24 { +macro_rules! ux { + ($type:ident) => { + impl From<$type> for u24 { + fn from(n: $type) -> Self { + assert!(n <= Self::MAX as $type); + Self(n as u32) + } + } + impl Into<$type> for u24 { + fn into(self) -> $type { + if (std::$type::MAX as u64) < (std::u16::MAX as u64) { + assert!(self.0 <= (std::$type::MAX as u32)); + } + self.0 as $type + } + } + }; +} + +macro_rules! ix { + ($type:ident) => { + impl From<$type> for u24 { + fn from(n: $type) -> Self { + assert!(n >= Self::MIN as $type && n <= Self::MAX as $type); + Self(n as u32) + } + } + impl Into<$type> for u24 { + fn into(self) -> $type { + if (std::$type::MAX as u64) < (std::u16::MAX as u64) { + assert!(self.0 <= (std::$type::MAX as u32)); + } + self.0 as $type + } + } + }; +} + +ux!(u8); +ux!(u16); +ux!(u32); +ux!(u64); +ux!(usize); +ix!(i8); +ix!(i16); +ix!(i32); +ix!(i64); +ix!(isize); + +impl Writeable for u24 { + fn write_to(&self, bf: &mut BytesMut) { + bf.put_u8((0xFF & (self.0 >> 16)) as u8); + bf.put_u8((0xFF & (self.0 >> 8)) as u8); + bf.put_u8((0xFF & self.0) as u8); + } + fn len(&self) -> usize { + 3 + } +} + +impl u24 { pub const MAX: u32 = 0x00FF_FFFF; pub const MIN: u32 = 0; - pub fn write(n: u32, bf: &mut BytesMut) { - bf.put_u8((0xFF & (n >> 16)) as u8); - bf.put_u8((0xFF & (n >> 8)) as u8); - bf.put_u8((0xFF & n) as u8); + pub fn parse(b: &[u8]) -> u24 { + assert!(b.len() > 2); + let mut n = 0u32; + n += (b[0] as u32) << 16; + n += (b[1] as u32) << 8; + n += b[2] as u32; + u24(n) } - pub fn read(bf: &mut BytesMut) -> u32 { - let mut n: u32 = 0; - n += u32::from(bf[0]) << 16; - n += u32::from(bf[1]) << 8; - n += u32::from(bf[2]); - n + pub fn read(bf: &mut BytesMut) -> u24 { + Self::parse(bf) } - pub fn read_advance(bf: &mut BytesMut) -> u32 { - let mut n: u32 = 0; + pub fn read_advance(bf: &mut BytesMut) -> u24 { let raw = bf.split_to(3); - n += u32::from(raw[0]) << 16; - n += u32::from(raw[1]) << 8; - n += u32::from(raw[2]); - n + Self::parse(&raw) } } From 2676bb406e46ecc01c70f3fbfeecb1711dc73715 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Sun, 10 May 2020 21:52:33 +0800 Subject: [PATCH 07/70] add messaging requester builder. --- examples/Cargo.toml | 2 +- rsocket-benchmark/Cargo.toml | 6 +- rsocket-messaging/Cargo.toml | 15 ++- rsocket-messaging/src/builder.rs | 48 ------- rsocket-messaging/src/lib.rs | 7 +- rsocket-messaging/src/requester.rs | 171 ++++++++++++++++++++++++- rsocket-test/Cargo.toml | 6 +- rsocket-test/tests/test_messaging.rs | 36 ++++-- rsocket-transport-tcp/Cargo.toml | 2 +- rsocket-transport-wasm/Cargo.toml | 14 +- rsocket-transport-websocket/Cargo.toml | 4 +- rsocket/Cargo.toml | 4 +- rsocket/src/utils.rs | 5 + 13 files changed, 234 insertions(+), 86 deletions(-) delete mode 100644 rsocket-messaging/src/builder.rs diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 487b36a..c51e88a 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -8,7 +8,7 @@ publish = false [dev-dependencies] log = "0.4.8" env_logger = "0.7.1" -futures = "0.3.4" +futures = "0.3.5" clap = "2.33.0" [dev-dependencies.rsocket_rust] diff --git a/rsocket-benchmark/Cargo.toml b/rsocket-benchmark/Cargo.toml index c6b70de..1572750 100644 --- a/rsocket-benchmark/Cargo.toml +++ b/rsocket-benchmark/Cargo.toml @@ -7,13 +7,13 @@ publish = false [dev-dependencies] log = "0.4" -futures = "0.3.4" +futures = "0.3.5" env_logger = "0.7.1" bytes = "0.5.4" hex = "0.4.2" rand = "0.7.3" -serde = "1.0.106" -serde_derive = "1.0.106" +serde = "1.0.110" +serde_derive = "1.0.110" criterion = "0.3.2" [dev-dependencies.rsocket_rust] diff --git a/rsocket-messaging/Cargo.toml b/rsocket-messaging/Cargo.toml index 8782ca6..bc0ed78 100644 --- a/rsocket-messaging/Cargo.toml +++ b/rsocket-messaging/Cargo.toml @@ -6,13 +6,20 @@ edition = "2018" [dependencies] log = "0.4.8" -futures = "0.3.4" +futures = "0.3.5" bytes = "0.5.4" -serde = "1.0.106" -serde_json = "1.0.52" +serde = "1.0.110" +serde_json = "1.0.53" serde_cbor = "0.11.1" hex = "0.4.2" +url = "2.1.1" [dependencies.rsocket_rust] path = "../rsocket" -features = ["frame"] \ No newline at end of file +features = ["frame"] + +[dependencies.rsocket_rust_transport_tcp] +path = "../rsocket-transport-tcp" + +[dependencies.rsocket_rust_transport_websocket] +path = "../rsocket-transport-websocket" \ No newline at end of file diff --git a/rsocket-messaging/src/builder.rs b/rsocket-messaging/src/builder.rs deleted file mode 100644 index c26fcbf..0000000 --- a/rsocket-messaging/src/builder.rs +++ /dev/null @@ -1,48 +0,0 @@ -use super::requester::Requester; -use rsocket_rust::extension::MimeType; - -pub struct RequesterBuilder { - data_mime_type: MimeType, - route: Option, - data: Option>, -} - -impl Default for RequesterBuilder { - fn default() -> Self { - Self { - data_mime_type: MimeType::APPLICATION_JSON, - route: None, - data: None, - } - } -} - -impl RequesterBuilder { - pub fn data_mime_type(mut self, mime_type: I) -> Self - where - I: Into, - { - self.data_mime_type = mime_type.into(); - self - } - - pub fn setup_route(mut self, route: I) -> Self - where - I: Into, - { - self.route = Some(route.into()); - self - } - - pub fn setup_data(mut self, data: D) -> Self - where - D: Into>, - { - self.data = Some(data.into()); - self - } - - pub fn build(self) -> Requester { - todo!("build requester") - } -} diff --git a/rsocket-messaging/src/lib.rs b/rsocket-messaging/src/lib.rs index 94229a9..5b8d09f 100644 --- a/rsocket-messaging/src/lib.rs +++ b/rsocket-messaging/src/lib.rs @@ -1,6 +1,7 @@ -mod builder; +#[macro_use] +extern crate log; + mod misc; mod requester; -pub use builder::RequesterBuilder; -pub use requester::{RequestSpec, Requester}; +pub use requester::{RequestSpec, Requester, RequesterBuilder}; diff --git a/rsocket-messaging/src/requester.rs b/rsocket-messaging/src/requester.rs index 0bd8f47..9ec8109 100644 --- a/rsocket-messaging/src/requester.rs +++ b/rsocket-messaging/src/requester.rs @@ -1,13 +1,25 @@ use super::misc::{marshal, unmarshal}; use bytes::BytesMut; use rsocket_rust::error::RSocketError; -use rsocket_rust::extension::{CompositeMetadata, MimeType, RoutingMetadata}; +use rsocket_rust::extension::{ + CompositeMetadata, CompositeMetadataEntry, MimeType, RoutingMetadata, +}; use rsocket_rust::prelude::*; use rsocket_rust::utils::Writeable; +use rsocket_rust_transport_tcp::TcpClientTransport; +use rsocket_rust_transport_websocket::WebsocketClientTransport; use serde::{Deserialize, Serialize}; use std::collections::LinkedList; use std::error::Error; +use std::net::SocketAddr; +use std::result::Result; use std::sync::Arc; +use url::Url; + +enum TransportKind { + TCP(String, u16), + WS(String), +} pub struct Requester { rsocket: Arc>, @@ -20,6 +32,159 @@ pub struct RequestSpec { metadatas: LinkedList<(MimeType, Vec)>, } +pub struct RequesterBuilder { + data_mime_type: Option, + route: Option, + metadata: Vec, + data: Option>, + tp: Option, +} + +impl Default for RequesterBuilder { + fn default() -> Self { + Self { + data_mime_type: None, + route: None, + metadata: Default::default(), + data: None, + tp: None, + } + } +} + +impl RequesterBuilder { + pub fn data_mime_type(mut self, mime_type: I) -> Self + where + I: Into, + { + self.data_mime_type = Some(mime_type.into()); + self + } + + pub fn setup_route(mut self, route: I) -> Self + where + I: Into, + { + self.route = Some(route.into()); + self + } + + pub fn setup_data(mut self, data: &D) -> Self + where + D: Sized + Serialize, + { + // TODO: lazy set + let mut bf = BytesMut::new(); + let result = match &self.data_mime_type { + Some(m) => marshal(m, &mut bf, data), + None => marshal(&MimeType::APPLICATION_JSON, &mut bf, data), + }; + match result { + Ok(()) => { + self.data = Some(bf.to_vec()); + } + Err(e) => { + error!("marshal failed: {:?}", e); + } + } + self + } + + pub fn setup_metadata(mut self, metadata: &M, mime_type: T) -> Self + where + M: Sized + Serialize, + T: Into, + { + // TODO: lazy set + let mut bf = BytesMut::new(); + let mime_type = mime_type.into(); + match marshal(&mime_type, &mut bf, metadata) { + Ok(()) => { + let entry = CompositeMetadataEntry::new(mime_type, bf.freeze()); + self.metadata.push(entry); + } + Err(e) => error!("marshal failed: {:?}", e), + } + self + } + + pub fn connect_tcp(mut self, host: A, port: u16) -> Self + where + A: Into, + { + self.tp = Some(TransportKind::TCP(host.into(), port)); + self + } + + pub fn connect_websocket(mut self, url: I) -> Self + where + I: Into, + { + self.tp = Some(TransportKind::WS(url.into())); + self + } + + pub async fn build(self) -> Result> { + let data_mime_type = self.data_mime_type.unwrap_or(MimeType::APPLICATION_JSON); + + let mut added = 0usize; + let mut composite_builder = CompositeMetadata::builder(); + + if let Some(s) = self.route { + let routing = RoutingMetadata::builder().push(s).build(); + composite_builder = + composite_builder.push(MimeType::MESSAGE_X_RSOCKET_ROUTING_V0, routing.bytes()); + added += 1; + } + for it in self.metadata.into_iter() { + composite_builder = composite_builder.push_entry(it); + added += 1; + } + + let mut payload_builder = Payload::builder(); + + if added > 0 { + payload_builder = payload_builder.set_metadata(composite_builder.build()); + } + + if let Some(raw) = self.data { + payload_builder = payload_builder.set_data(raw); + } + + let setup = payload_builder.build(); + + match self.tp { + Some(TransportKind::TCP(h, p)) => { + let addr: SocketAddr = format!("{}:{}", h, p).parse()?; + let cli = RSocketFactory::connect() + .data_mime_type(data_mime_type.as_ref()) + .setup(setup) + .metadata_mime_type(MimeType::MESSAGE_X_RSOCKET_COMPOSITE_METADATA_V0.as_ref()) + .transport(TcpClientTransport::from(addr)) + .start() + .await?; + let rsocket: Box = Box::new(cli); + let requester = Requester::from(rsocket); + Ok(requester) + } + Some(TransportKind::WS(u)) => { + let url = Url::parse(&u)?; + let cli = RSocketFactory::connect() + .data_mime_type(data_mime_type.as_ref()) + .setup(setup) + .metadata_mime_type(MimeType::MESSAGE_X_RSOCKET_COMPOSITE_METADATA_V0.as_ref()) + .transport(WebsocketClientTransport::from(url)) + .start() + .await?; + let rsocket: Box = Box::new(cli); + let requester = Requester::from(rsocket); + Ok(requester) + } + None => Err("Missing transport!".into()), + } + } +} + impl From> for Requester { fn from(rsocket: Box) -> Requester { Requester { @@ -29,6 +194,10 @@ impl From> for Requester { } impl Requester { + pub fn builder() -> RequesterBuilder { + RequesterBuilder::default() + } + pub fn route(&self, route: &str) -> RequestSpec { let routing = RoutingMetadata::builder().push_str(route).build(); let mut buf = BytesMut::new(); diff --git a/rsocket-test/Cargo.toml b/rsocket-test/Cargo.toml index 1023dcf..9d05b99 100644 --- a/rsocket-test/Cargo.toml +++ b/rsocket-test/Cargo.toml @@ -7,13 +7,13 @@ publish = false [dev-dependencies] log = "0.4" -futures = "0.3.4" +futures = "0.3.5" env_logger = "0.7.1" bytes = "0.5.4" hex = "0.4.2" rand = "0.7.3" -serde = "1.0.106" -serde_derive = "1.0.106" +serde = "1.0.110" +serde_derive = "1.0.110" [dev-dependencies.rsocket_rust] path = "../rsocket" diff --git a/rsocket-test/tests/test_messaging.rs b/rsocket-test/tests/test_messaging.rs index 06c3d16..f4b00ac 100644 --- a/rsocket-test/tests/test_messaging.rs +++ b/rsocket-test/tests/test_messaging.rs @@ -3,9 +3,21 @@ extern crate log; #[macro_use] extern crate serde_derive; -use rsocket_rust::prelude::*; +use rsocket_rust::extension::MimeType; use rsocket_rust_messaging::*; -use rsocket_rust_transport_tcp::TcpClientTransport; + +fn init() { + let _ = env_logger::builder() + .format_timestamp_millis() + .is_test(true) + .try_init(); +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct Token { + app: String, + access: String, +} #[derive(Serialize, Deserialize, Debug)] pub struct Student { @@ -25,17 +37,19 @@ pub struct Response { #[test] #[ignore] async fn test_messaging() { - let rsocket = RSocketFactory::connect() - .transport(TcpClientTransport::from("tcp://127.0.0.1:7878")) - .data_mime_type("application/json") - .metadata_mime_type("message/x.rsocket.composite-metadata.v0") - .start() + init(); + let token = Token { + app: "xxx".to_owned(), + access: "yyy".to_owned(), + }; + let requester = Requester::builder() + .setup_metadata(&token, MimeType::APPLICATION_JSON) + .setup_data(&token) + .connect_tcp("127.0.0.1", 7878) + .build() .await .expect("Connect failed!"); - let rsocket: Box = Box::new(rsocket); - let requester = Requester::from(rsocket); - let post = Student { id: 1234, name: "Jeffsky".to_owned(), @@ -52,5 +66,5 @@ async fn test_messaging() { .block() .expect("Retrieve failed!") .expect("Empty result!"); - println!("------> RESPONSE: {:?}", res); + info!("------> RESPONSE: {:?}", res); } diff --git a/rsocket-transport-tcp/Cargo.toml b/rsocket-transport-tcp/Cargo.toml index 2c93762..5c2762a 100644 --- a/rsocket-transport-tcp/Cargo.toml +++ b/rsocket-transport-tcp/Cargo.toml @@ -11,7 +11,7 @@ description = "TCP RSocket transport implementation." [dependencies] log = "0.4.8" -futures = "0.3.4" +futures = "0.3.5" bytes = "0.5.4" [dependencies.rsocket_rust] diff --git a/rsocket-transport-wasm/Cargo.toml b/rsocket-transport-wasm/Cargo.toml index 3a9bb30..a230c84 100644 --- a/rsocket-transport-wasm/Cargo.toml +++ b/rsocket-transport-wasm/Cargo.toml @@ -11,19 +11,19 @@ description = "WASM Websocket RSocket transport implementation." [dependencies] bytes = "0.5.4" -wasm-bindgen-futures = "0.4.10" -futures-channel = "0.3.4" -futures-util = "0.3.4" -js-sys = "0.3.37" -serde = "1.0.106" -serde_derive = "1.0.106" +wasm-bindgen-futures = "0.4.12" +futures-channel = "0.3.5" +futures-util = "0.3.5" +js-sys = "0.3.39" +serde = "1.0.110" +serde_derive = "1.0.110" [dependencies.rsocket_rust] path = "../rsocket" features = ["frame"] [dependencies.wasm-bindgen] -version = "0.2.60" +version = "0.2.62" features = ["serde-serialize"] [dependencies.web-sys] diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index 6af15e7..631f5bc 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -11,7 +11,7 @@ description = "Websocket RSocket transport implementation." [dependencies] log = "0.4.8" -futures = "0.3.4" +futures = "0.3.5" bytes = "0.5.4" url = "2.1.1" tokio-tungstenite = "0.10.1" @@ -21,6 +21,6 @@ path = "../rsocket" features = ["frame"] [dependencies.tokio] -version = "0.2.19" +version = "0.2.20" default-features = false features = [ "rt-core", "rt-threaded", "tcp", "sync", "stream" ] diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index 76e6ae8..b350f20 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -12,11 +12,11 @@ description = "rsocket-rust is an implementation of the RSocket protocol in Rust [dependencies] log = "0.4.8" bytes = "0.5.4" -futures = "0.3.4" +futures = "0.3.5" lazy_static = "1.4.0" [dependencies.tokio] -version = "0.2.19" +version = "0.2.20" default-features = false features = [ "rt-core", "rt-threaded", "sync", "stream" ] diff --git a/rsocket/src/utils.rs b/rsocket/src/utils.rs index 8d06dfb..b928d34 100644 --- a/rsocket/src/utils.rs +++ b/rsocket/src/utils.rs @@ -15,6 +15,11 @@ pub trait Writeable { fn is_empty(&self) -> bool { self.len() == 0 } + fn bytes(&self) -> Vec { + let mut b = BytesMut::new(); + self.write_to(&mut b); + b.to_vec() + } } #[allow(non_camel_case_types)] From 3987e2c99292a30a9cb004c32c19521abd82f05c Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Sun, 17 May 2020 22:32:42 +0800 Subject: [PATCH 08/70] Change messaging RequestSpec to fluent api. --- rsocket-messaging/Cargo.toml | 1 + rsocket-messaging/src/lib.rs | 3 + rsocket-messaging/src/misc.rs | 93 +++++++++++------ rsocket-messaging/src/requester.rs | 145 ++++++++++++++++++--------- rsocket-test/tests/test_messaging.rs | 22 ++-- 5 files changed, 177 insertions(+), 87 deletions(-) diff --git a/rsocket-messaging/Cargo.toml b/rsocket-messaging/Cargo.toml index bc0ed78..575fcd0 100644 --- a/rsocket-messaging/Cargo.toml +++ b/rsocket-messaging/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" log = "0.4.8" futures = "0.3.5" bytes = "0.5.4" +lazy_static = "1.4.0" serde = "1.0.110" serde_json = "1.0.53" serde_cbor = "0.11.1" diff --git a/rsocket-messaging/src/lib.rs b/rsocket-messaging/src/lib.rs index 5b8d09f..c663c8a 100644 --- a/rsocket-messaging/src/lib.rs +++ b/rsocket-messaging/src/lib.rs @@ -1,7 +1,10 @@ #[macro_use] extern crate log; +// #[macro_use] +// extern crate lazy_static; mod misc; mod requester; +pub use misc::{cbor, json, SerDe}; pub use requester::{RequestSpec, Requester, RequesterBuilder}; diff --git a/rsocket-messaging/src/misc.rs b/rsocket-messaging/src/misc.rs index 51d8379..974309c 100644 --- a/rsocket-messaging/src/misc.rs +++ b/rsocket-messaging/src/misc.rs @@ -1,38 +1,73 @@ -use bytes::{BufMut, BytesMut}; -use rsocket_rust::extension::MimeType; -use serde::{Deserialize, Serialize}; +use serde::{de::DeserializeOwned, Serialize}; use std::error::Error; -pub(crate) fn unmarshal<'a, T>(mime_type: &MimeType, raw: &'a [u8]) -> Result> -where - T: Deserialize<'a>, -{ - match *mime_type { - MimeType::APPLICATION_JSON => Ok(serde_json::from_slice(raw)?), - MimeType::APPLICATION_CBOR => Ok(serde_cbor::from_slice(raw)?), - _ => panic!(""), +pub trait SerDe { + fn marshal(&self, data: &T) -> Result, Box> + where + Self: Sized, + T: Sized + Serialize; + + fn unmarshal(&self, raw: &[u8]) -> Result> + where + Self: Sized, + T: Sized + DeserializeOwned; +} + +#[derive(Default)] +struct JsonSerDe {} + +impl SerDe for JsonSerDe { + fn marshal(&self, data: &T) -> Result, Box> + where + T: Sized + Serialize, + { + Ok(serde_json::to_vec(data)?) } + + fn unmarshal(&self, raw: &[u8]) -> Result> + where + T: Sized + DeserializeOwned, + { + Ok(serde_json::from_slice(raw)?) + } +} + +pub fn json() -> impl SerDe { + JsonSerDe {} +} + +pub fn cbor() -> impl SerDe { + CborSerDe {} } -pub(crate) fn marshal( - mime_type: &MimeType, - bf: &mut BytesMut, - data: &T, -) -> Result<(), Box> +struct CborSerDe {} + +impl SerDe for CborSerDe { + fn marshal(&self, data: &T) -> Result, Box> + where + T: Sized + Serialize, + { + Ok(serde_cbor::to_vec(data)?) + } + + fn unmarshal(&self, raw: &[u8]) -> Result> + where + T: Sized + DeserializeOwned, + { + Ok(serde_cbor::from_slice(raw)?) + } +} + +pub(crate) fn marshal(ser: impl SerDe, data: &T) -> Result, Box> where T: Sized + Serialize, { - match *mime_type { - MimeType::APPLICATION_JSON => { - let raw = serde_json::to_vec(data)?; - bf.put_slice(&raw[..]); - Ok(()) - } - MimeType::APPLICATION_CBOR => { - let raw = serde_cbor::to_vec(data)?; - bf.put_slice(&raw[..]); - Ok(()) - } - _ => panic!(""), - } + ser.marshal(data) +} + +pub(crate) fn unmarshal(de: impl SerDe, raw: &[u8]) -> Result> +where + T: Sized + DeserializeOwned, +{ + de.unmarshal(raw) } diff --git a/rsocket-messaging/src/requester.rs b/rsocket-messaging/src/requester.rs index 9ec8109..4050ed3 100644 --- a/rsocket-messaging/src/requester.rs +++ b/rsocket-messaging/src/requester.rs @@ -1,5 +1,5 @@ -use super::misc::{marshal, unmarshal}; -use bytes::BytesMut; +use super::misc::{self, marshal, unmarshal}; +use bytes::{Bytes, BytesMut}; use rsocket_rust::error::RSocketError; use rsocket_rust::extension::{ CompositeMetadata, CompositeMetadataEntry, MimeType, RoutingMetadata, @@ -8,7 +8,7 @@ use rsocket_rust::prelude::*; use rsocket_rust::utils::Writeable; use rsocket_rust_transport_tcp::TcpClientTransport; use rsocket_rust_transport_websocket::WebsocketClientTransport; -use serde::{Deserialize, Serialize}; +use serde::{de::DeserializeOwned, Serialize}; use std::collections::LinkedList; use std::error::Error; use std::net::SocketAddr; @@ -16,6 +16,10 @@ use std::result::Result; use std::sync::Arc; use url::Url; +type FnMetadata = Box Result<(MimeType, Vec), Box>>; +type FnData = Box Result, Box>>; +type PreflightResult = Result<(Payload, MimeType, Arc>), Box>; + enum TransportKind { TCP(String, u16), WS(String), @@ -26,10 +30,10 @@ pub struct Requester { } pub struct RequestSpec { - data: Option>, rsocket: Arc>, data_mime_type: MimeType, - metadatas: LinkedList<(MimeType, Vec)>, + metadatas: LinkedList, + data: Option, } pub struct RequesterBuilder { @@ -74,14 +78,13 @@ impl RequesterBuilder { D: Sized + Serialize, { // TODO: lazy set - let mut bf = BytesMut::new(); let result = match &self.data_mime_type { - Some(m) => marshal(m, &mut bf, data), - None => marshal(&MimeType::APPLICATION_JSON, &mut bf, data), + Some(m) => do_marshal(m, data), + None => do_marshal(&MimeType::APPLICATION_JSON, data), }; match result { - Ok(()) => { - self.data = Some(bf.to_vec()); + Ok(raw) => { + self.data = Some(raw); } Err(e) => { error!("marshal failed: {:?}", e); @@ -96,11 +99,10 @@ impl RequesterBuilder { T: Into, { // TODO: lazy set - let mut bf = BytesMut::new(); let mime_type = mime_type.into(); - match marshal(&mime_type, &mut bf, metadata) { - Ok(()) => { - let entry = CompositeMetadataEntry::new(mime_type, bf.freeze()); + match do_marshal(&mime_type, metadata) { + Ok(raw) => { + let entry = CompositeMetadataEntry::new(mime_type, Bytes::from(raw)); self.metadata.push(entry); } Err(e) => error!("marshal failed: {:?}", e), @@ -203,100 +205,143 @@ impl Requester { let mut buf = BytesMut::new(); routing.write_to(&mut buf); - let mut metadatas: LinkedList<(MimeType, Vec)> = Default::default(); - metadatas.push_back((MimeType::MESSAGE_X_RSOCKET_ROUTING_V0, buf.to_vec())); + let mut metadatas: LinkedList = LinkedList::new(); + metadatas.push_back(Box::new(move || { + Ok((MimeType::MESSAGE_X_RSOCKET_ROUTING_V0, buf.to_vec())) + })); + RequestSpec { - data: None, rsocket: self.rsocket.clone(), data_mime_type: MimeType::APPLICATION_JSON, metadatas, + data: None, } } } impl RequestSpec { - pub fn metadata(&mut self, metadata: &T, mime_type: M) -> Result<(), Box> + pub fn metadata(mut self, metadata: T, mime_type: M) -> Self where - T: Sized + Serialize, + T: Sized + Serialize + 'static, M: Into, { let mime_type = mime_type.into(); - let mut b = BytesMut::new(); - marshal(&mime_type, &mut b, metadata)?; - self.metadatas.push_back((mime_type, b.to_vec())); - Ok(()) + let f: FnMetadata = Box::new(move || { + let raw = do_marshal(&mime_type, &metadata)?; + Ok((mime_type.clone(), raw)) + }); + self.metadatas.push_back(f); + self } - pub fn metadata_raw(&mut self, metadata: I, mime_type: M) -> Result<(), Box> + pub fn metadata_raw(mut self, metadata: I, mime_type: M) -> Self where I: Into>, M: Into, { + let mime_type = mime_type.into(); + let metadata = metadata.into(); self.metadatas - .push_back((mime_type.into(), metadata.into())); - Ok(()) + .push_back(Box::new(move || Ok((mime_type.clone(), metadata.clone())))); + self } - pub fn data(&mut self, data: &T) -> Result<(), Box> + pub fn data(mut self, data: T) -> Self where - T: Sized + Serialize, + T: Sized + Serialize + 'static, { - let mut bf = BytesMut::new(); - marshal(&self.data_mime_type, &mut bf, data)?; - self.data = Some(bf.to_vec()); - Ok(()) + self.data = Some(Box::new(move |m| do_marshal(m, &data))); + self } - pub fn data_raw(&mut self, data: I) -> Result<(), Box> + pub fn data_raw(mut self, data: I) -> Self where I: Into>, { - self.data = Some(data.into()); - Ok(()) + let data = data.into(); + self.data = Some(Box::new(move |_m| Ok(data.clone()))); + self } pub async fn retrieve_mono(self) -> Unpacker { - let (req, mime_type, rsocket) = self.preflight(); - let res = rsocket.request_response(req).await; - Unpacker { - mime_type, - inner: res, + match self.preflight() { + Ok((req, mime_type, rsocket)) => { + let res = rsocket.request_response(req).await; + match res { + Ok(v) => Unpacker { + inner: Ok((mime_type, v)), + }, + Err(e) => Unpacker { inner: Err(e) }, + } + } + Err(e) => { + // TODO: better error + let msg = format!("{}", e); + Unpacker { + inner: Err(RSocketError::from(msg)), + } + } } } #[inline] - fn preflight(self) -> (Payload, MimeType, Arc>) { + fn preflight(self) -> PreflightResult { let mut b = BytesMut::new(); let mut c = CompositeMetadata::builder(); - for (mime_type, raw) in self.metadatas.into_iter() { + + for mut b in self.metadatas.into_iter() { + let (mime_type, raw) = b()?; c = c.push(mime_type, raw); } c.build().write_to(&mut b); let mut bu = Payload::builder().set_metadata(b.to_vec()); - if let Some(raw) = self.data { + if let Some(mut gen) = self.data { + let raw = gen(&self.data_mime_type)?; bu = bu.set_data(raw); } - (bu.build(), self.data_mime_type, self.rsocket) + Ok((bu.build(), self.data_mime_type, self.rsocket)) } } pub struct Unpacker { - mime_type: MimeType, - inner: Result, + inner: Result<(MimeType, Payload), RSocketError>, } impl Unpacker { - pub fn block<'a, T>(&'a self) -> Result, Box> + pub fn block(&self) -> Result, Box> where - T: Deserialize<'a>, + T: Sized + DeserializeOwned, { match &self.inner { - Ok(inner) => match inner.data() { - Some(raw) => Ok(Some(unmarshal(&self.mime_type, &raw.as_ref())?)), + Ok((mime_type, inner)) => match inner.data() { + // TODO: support more mime types. + Some(raw) => match *mime_type { + MimeType::APPLICATION_JSON => { + let t = unmarshal(misc::json(), &raw.as_ref())?; + Ok(Some(t)) + } + MimeType::APPLICATION_CBOR => { + let t = unmarshal(misc::cbor(), &raw.as_ref())?; + Ok(Some(t)) + } + _ => Err("unsupported mime type!".into()), + }, None => Ok(None), }, Err(e) => Err(format!("{}", e).into()), } } } + +fn do_marshal(mime_type: &MimeType, data: &T) -> Result, Box> +where + T: Sized + Serialize, +{ + // TODO: support more mime types + match *mime_type { + MimeType::APPLICATION_JSON => marshal(misc::json(), data), + MimeType::APPLICATION_CBOR => marshal(misc::cbor(), data), + _ => Err("unsupported mime type!".into()), + } +} diff --git a/rsocket-test/tests/test_messaging.rs b/rsocket-test/tests/test_messaging.rs index f4b00ac..3116b02 100644 --- a/rsocket-test/tests/test_messaging.rs +++ b/rsocket-test/tests/test_messaging.rs @@ -13,19 +13,25 @@ fn init() { .try_init(); } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Default)] pub struct Token { app: String, access: String, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Default)] pub struct Student { id: i64, name: String, birth: String, } +#[derive(Serialize, Deserialize, Debug, Default)] +pub struct Tracing { + id: String, + ts: i64, +} + #[derive(Serialize, Deserialize, Debug)] pub struct Response { code: i32, @@ -55,12 +61,12 @@ async fn test_messaging() { name: "Jeffsky".to_owned(), birth: "2020-01-01".to_owned(), }; - let mut req = requester.route("student.v1.upsert"); - req.metadata_raw("raw metadata", "application/json") - .unwrap(); - req.metadata(&post, "application/json").unwrap(); - req.data(&post).unwrap(); - let res: Response = req + + let res: Response = requester + .route("student.v1.upsert") + .metadata(Tracing::default(), "application/json") + .metadata_raw("foobar", "message/x.rsocket.authentication.bearer.v0") + .data(post) .retrieve_mono() .await .block() From 50bdcd1859d438661b808b60324e21bb9e8f85c8 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Tue, 19 May 2020 22:52:05 +0800 Subject: [PATCH 09/70] Support flux result for messaging requester. --- rsocket-messaging/src/requester.rs | 109 +++++++++++++++++++++++---- rsocket-test/tests/test_messaging.rs | 40 ++++++++-- 2 files changed, 126 insertions(+), 23 deletions(-) diff --git a/rsocket-messaging/src/requester.rs b/rsocket-messaging/src/requester.rs index 4050ed3..fb69d82 100644 --- a/rsocket-messaging/src/requester.rs +++ b/rsocket-messaging/src/requester.rs @@ -19,6 +19,8 @@ use url::Url; type FnMetadata = Box Result<(MimeType, Vec), Box>>; type FnData = Box Result, Box>>; type PreflightResult = Result<(Payload, MimeType, Arc>), Box>; +type UnpackerResult = Result<(MimeType, Payload), RSocketError>; +type UnpackersResult = Result<(MimeType, Flux>), Box>; enum TransportKind { TCP(String, u16), @@ -44,6 +46,14 @@ pub struct RequesterBuilder { tp: Option, } +pub struct Unpackers { + inner: UnpackersResult, +} + +pub struct Unpacker { + inner: UnpackerResult, +} + impl Default for RequesterBuilder { fn default() -> Self { Self { @@ -263,6 +273,16 @@ impl RequestSpec { self } + pub async fn retrieve(self) -> Result<(), Box> { + match self.preflight() { + Ok((req, _mime_type, rsocket)) => { + rsocket.fire_and_forget(req).await; + Ok(()) + } + Err(e) => Err(e), + } + } + pub async fn retrieve_mono(self) -> Unpacker { match self.preflight() { Ok((req, mime_type, rsocket)) => { @@ -284,6 +304,18 @@ impl RequestSpec { } } + pub fn retrieve_flux(self) -> Unpackers { + match self.preflight() { + Ok((req, mime_type, rsocket)) => { + let results = rsocket.request_stream(req); + Unpackers { + inner: Ok((mime_type, results)), + } + } + Err(e) => Unpackers { inner: Err(e) }, + } + } + #[inline] fn preflight(self) -> PreflightResult { let mut b = BytesMut::new(); @@ -304,29 +336,59 @@ impl RequestSpec { } } -pub struct Unpacker { - inner: Result<(MimeType, Payload), RSocketError>, +impl Unpackers { + pub async fn block(self) -> Result, Box> + where + T: Sized + DeserializeOwned, + { + let (mime_type, mut results) = self.inner?; + let mut res = Vec::new(); + while let Some(next) = results.next().await { + match next { + Ok(v) => { + if let Some(data) = v.data() { + let t = do_unmarshal::(&mime_type, data)?; + if let Some(t) = t { + res.push(t); + } + } + } + Err(e) => return Err(format!("{}", e).into()), + } + } + Ok(res) + } + pub async fn foreach(self, callback: impl Fn(T)) -> Result<(), Box> + where + T: Sized + DeserializeOwned, + { + let (mime_type, mut results) = self.inner?; + while let Some(next) = results.next().await { + match next { + Ok(v) => { + if let Some(data) = v.data() { + let t = do_unmarshal::(&mime_type, data)?; + if let Some(t) = t { + callback(t); + } + } + } + Err(e) => return Err(format!("{}", e).into()), + } + } + Ok(()) + } } impl Unpacker { - pub fn block(&self) -> Result, Box> + pub fn block(self) -> Result, Box> where T: Sized + DeserializeOwned, { - match &self.inner { + match self.inner { Ok((mime_type, inner)) => match inner.data() { // TODO: support more mime types. - Some(raw) => match *mime_type { - MimeType::APPLICATION_JSON => { - let t = unmarshal(misc::json(), &raw.as_ref())?; - Ok(Some(t)) - } - MimeType::APPLICATION_CBOR => { - let t = unmarshal(misc::cbor(), &raw.as_ref())?; - Ok(Some(t)) - } - _ => Err("unsupported mime type!".into()), - }, + Some(raw) => do_unmarshal(&mime_type, raw), None => Ok(None), }, Err(e) => Err(format!("{}", e).into()), @@ -334,6 +396,23 @@ impl Unpacker { } } +fn do_unmarshal(mime_type: &MimeType, raw: &Bytes) -> Result, Box> +where + T: Sized + DeserializeOwned, +{ + match *mime_type { + MimeType::APPLICATION_JSON => { + let t = unmarshal(misc::json(), &raw.as_ref())?; + Ok(Some(t)) + } + MimeType::APPLICATION_CBOR => { + let t = unmarshal(misc::cbor(), &raw.as_ref())?; + Ok(Some(t)) + } + _ => Err("unsupported mime type!".into()), + } +} + fn do_marshal(mime_type: &MimeType, data: &T) -> Result, Box> where T: Sized + Serialize, diff --git a/rsocket-test/tests/test_messaging.rs b/rsocket-test/tests/test_messaging.rs index 3116b02..4f1bde1 100644 --- a/rsocket-test/tests/test_messaging.rs +++ b/rsocket-test/tests/test_messaging.rs @@ -19,7 +19,7 @@ pub struct Token { access: String, } -#[derive(Serialize, Deserialize, Debug, Default)] +#[derive(Serialize, Deserialize, Debug, Default, Clone)] pub struct Student { id: i64, name: String, @@ -56,21 +56,45 @@ async fn test_messaging() { .await .expect("Connect failed!"); - let post = Student { - id: 1234, - name: "Jeffsky".to_owned(), - birth: "2020-01-01".to_owned(), - }; - + // TEST MONO BEGIN let res: Response = requester .route("student.v1.upsert") .metadata(Tracing::default(), "application/json") .metadata_raw("foobar", "message/x.rsocket.authentication.bearer.v0") - .data(post) + .data(next_post()) .retrieve_mono() .await .block() .expect("Retrieve failed!") .expect("Empty result!"); info!("------> RESPONSE: {:?}", res); + + // TEST FLUX BEGIN + let res: Vec = requester + .route("students.v1") + .data(next_post()) + .retrieve_flux() + .block() + .await + .expect("Retrieve failed!"); + for it in res.iter() { + info!("===> NEXT: {:?}", it); + } + requester + .route("students.v1") + .data(next_post()) + .retrieve_flux() + .foreach(|it: Student| { + info!("===> FOREACH: {:?}", it); + }) + .await + .expect("Retrieve failed!"); +} + +fn next_post() -> Student { + Student { + id: 1234, + name: "Jeffsky".to_owned(), + birth: "2020-01-01".to_owned(), + } } From 0ebbc486aa2a2003fda8618786de55af9881776b Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Thu, 21 May 2020 23:03:24 +0800 Subject: [PATCH 10/70] Add length check for frames. --- rsocket-test/tests/test_composite_metadata.rs | 14 +++++- rsocket-test/tests/test_mimes.rs | 26 +++++++++++ rsocket/src/error.rs | 2 + rsocket/src/extension/mime.rs | 5 +-- rsocket/src/frame/error.rs | 17 +++++--- rsocket/src/frame/keepalive.rs | 15 ++++--- rsocket/src/frame/lease.rs | 4 ++ rsocket/src/frame/mod.rs | 6 ++- rsocket/src/frame/payload.rs | 7 +-- rsocket/src/frame/request_channel.rs | 18 +++++--- rsocket/src/frame/request_fnf.rs | 4 +- rsocket/src/frame/request_n.rs | 9 +++- rsocket/src/frame/request_response.rs | 4 +- rsocket/src/frame/request_stream.rs | 18 +++++--- rsocket/src/frame/resume.rs | 22 +++++++--- rsocket/src/frame/resume_ok.rs | 10 ++++- rsocket/src/frame/setup.rs | 37 +++++++++++++--- rsocket/src/frame/utils.rs | 43 ++++++++++++------- 18 files changed, 186 insertions(+), 75 deletions(-) diff --git a/rsocket-test/tests/test_composite_metadata.rs b/rsocket-test/tests/test_composite_metadata.rs index baf3b04..c6b39e5 100644 --- a/rsocket-test/tests/test_composite_metadata.rs +++ b/rsocket-test/tests/test_composite_metadata.rs @@ -1,9 +1,9 @@ -use bytes::BytesMut; +use bytes::{BufMut, BytesMut}; use rsocket_rust::extension::{self, CompositeMetadata, CompositeMetadataEntry, MimeType}; use rsocket_rust::utils::Writeable; #[test] -fn encode_and_decode_composite_metadata() { +fn test_encode_and_decode() { let bingo = |metadatas: Vec<&CompositeMetadataEntry>| { assert_eq!(2, metadatas.len()); assert_eq!( @@ -29,3 +29,13 @@ fn encode_and_decode_composite_metadata() { let cm2 = CompositeMetadata::decode(&mut bf).unwrap(); bingo(cm2.iter().collect()); } + +#[test] +fn test_bad() { + let mut bf = BytesMut::new(); + bf.put_slice(b"must bad"); + assert!( + CompositeMetadata::decode(&mut bf).is_err(), + "should be error" + ) +} diff --git a/rsocket-test/tests/test_mimes.rs b/rsocket-test/tests/test_mimes.rs index f401529..16c0386 100644 --- a/rsocket-test/tests/test_mimes.rs +++ b/rsocket-test/tests/test_mimes.rs @@ -2,6 +2,15 @@ extern crate rsocket_rust; use rsocket_rust::extension::{self, MimeType}; +#[test] +fn test_from_str() { + let result = MimeType::from("foobar"); + match result { + MimeType::WellKnown(_) => panic!("failed"), + MimeType::Normal(s) => assert_eq!(&s, "foobar"), + } +} + #[test] fn test_wellknown() { let well = MimeType::from("application/json"); @@ -10,3 +19,20 @@ fn test_wellknown() { let custom = MimeType::from("application/custom"); assert_eq!(MimeType::Normal("application/custom".to_owned()), custom); } + +#[test] +fn test_parse() { + assert!(MimeType::parse(0xFF).is_none(), "should be none"); + for x in 0..0x29 { + assert!(MimeType::parse(x).is_some(), "should not be none"); + } + for x in 0x29..0x7A { + assert!(MimeType::parse(x).is_none(), "should be none"); + } + for x in 0x7A..0x80 { + assert!(MimeType::parse(x).is_some(), "should not be none"); + } + for x in 0x80..0xFF { + assert!(MimeType::parse(x).is_none(), "should be none"); + } +} diff --git a/rsocket/src/error.rs b/rsocket/src/error.rs index a12f388..b4819b1 100644 --- a/rsocket/src/error.rs +++ b/rsocket/src/error.rs @@ -19,6 +19,7 @@ pub enum ErrorKind { WithDescription(String), IO(io::Error), Cancelled(), + LengthTooShort(usize), } #[derive(Debug)] @@ -35,6 +36,7 @@ impl fmt::Display for RSocketError { ErrorKind::WithDescription(s) => write!(f, "{}", s), ErrorKind::IO(e) => write!(f, "{}", e), ErrorKind::Cancelled() => write!(f, "ERROR(CANCELLED)"), + ErrorKind::LengthTooShort(n) => write!(f, "ERROR(MINIMAL LENGTH {})", n), } } } diff --git a/rsocket/src/extension/mime.rs b/rsocket/src/extension/mime.rs index 0314117..47ffb22 100644 --- a/rsocket/src/extension/mime.rs +++ b/rsocket/src/extension/mime.rs @@ -16,9 +16,6 @@ lazy_static! { } m }; -} - -lazy_static! { static ref STR_TO_U8: HashMap<&'static str, u8> = { let mut m = HashMap::new(); for it in list_all().iter() { @@ -58,7 +55,7 @@ impl AsRef for MimeType { impl From<&str> for MimeType { fn from(value: &str) -> MimeType { - match STR_TO_U8.get(&value) { + match STR_TO_U8.get(value) { Some(v) => Self::WellKnown(*v), None => Self::Normal(value.to_owned()), } diff --git a/rsocket/src/frame/error.rs b/rsocket/src/frame/error.rs index d7cff9a..86943cc 100644 --- a/rsocket/src/frame/error.rs +++ b/rsocket/src/frame/error.rs @@ -1,3 +1,4 @@ +use super::utils::too_short; use super::{Body, Frame}; use crate::utils::{RSocketResult, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -44,13 +45,17 @@ impl ErrorBuilder { impl Error { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { - let code = bf.get_u32(); - let d: Option = if !bf.is_empty() { - Some(bf.to_bytes()) + if bf.len() < 4 { + too_short(4) } else { - None - }; - Ok(Error { code, data: d }) + let code = bf.get_u32(); + let data: Option = if !bf.is_empty() { + Some(bf.to_bytes()) + } else { + None + }; + Ok(Error { code, data }) + } } pub fn builder(stream_id: u32, flag: u16) -> ErrorBuilder { diff --git a/rsocket/src/frame/keepalive.rs b/rsocket/src/frame/keepalive.rs index c1826ea..f25d586 100644 --- a/rsocket/src/frame/keepalive.rs +++ b/rsocket/src/frame/keepalive.rs @@ -1,3 +1,4 @@ +use super::utils::too_short; use super::{Body, Frame}; use crate::utils::{RSocketResult, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -43,14 +44,18 @@ impl KeepaliveBuilder { impl Keepalive { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { - let position = bf.get_u64(); - let mut d: Option = None; - if !bf.is_empty() { - d = Some(bf.to_bytes()); + if bf.len() < 8 { + return too_short(8); } + let position = bf.get_u64(); + let data = if bf.is_empty() { + None + } else { + Some(bf.to_bytes()) + }; Ok(Keepalive { last_received_position: position, - data: d, + data, }) } diff --git a/rsocket/src/frame/lease.rs b/rsocket/src/frame/lease.rs index e3fce69..847ef33 100644 --- a/rsocket/src/frame/lease.rs +++ b/rsocket/src/frame/lease.rs @@ -1,3 +1,4 @@ +use super::utils::too_short; use super::{Body, Frame}; use crate::utils::{RSocketResult, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -51,6 +52,9 @@ impl LeaseBuilder { impl Lease { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { + if bf.len() < 8 { + return too_short(8); + } let ttl = bf.get_u32(); let n = bf.get_u32(); let m = if flag & Frame::FLAG_METADATA != 0 { diff --git a/rsocket/src/frame/mod.rs b/rsocket/src/frame/mod.rs index 515d9a5..b0cfd4c 100644 --- a/rsocket/src/frame/mod.rs +++ b/rsocket/src/frame/mod.rs @@ -1,4 +1,4 @@ -use crate::error::RSocketError; +use crate::error::{ErrorKind, RSocketError}; use crate::utils::{RSocketResult, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -145,7 +145,9 @@ impl Frame { } pub fn decode(b: &mut BytesMut) -> RSocketResult { - // TODO: check size + if b.len() < LEN_HEADER { + return Err(ErrorKind::LengthTooShort(LEN_HEADER).into()); + } let sid = b.get_u32(); let n = b.get_u16(); let (flag, kind) = (n & 0x03FF, (n & 0xFC00) >> 10); diff --git a/rsocket/src/frame/payload.rs b/rsocket/src/frame/payload.rs index 22adfa5..20a7ec8 100644 --- a/rsocket/src/frame/payload.rs +++ b/rsocket/src/frame/payload.rs @@ -1,3 +1,4 @@ +use super::utils::{read_payload, too_short}; use super::{Body, Frame, PayloadSupport}; use crate::utils::{RSocketResult, Writeable}; use bytes::{BufMut, Bytes, BytesMut}; @@ -59,11 +60,7 @@ impl PayloadBuilder { impl Payload { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { - let (m, d) = PayloadSupport::read(flag, bf); - Ok(Payload { - metadata: m, - data: d, - }) + read_payload(flag, bf).map(|(metadata, data)| Payload { metadata, data }) } pub fn builder(stream_id: u32, flag: u16) -> PayloadBuilder { diff --git a/rsocket/src/frame/request_channel.rs b/rsocket/src/frame/request_channel.rs index 0244bc1..67f80bf 100644 --- a/rsocket/src/frame/request_channel.rs +++ b/rsocket/src/frame/request_channel.rs @@ -1,3 +1,4 @@ +use super::utils::{read_payload, too_short}; use super::{Body, Frame, PayloadSupport, REQUEST_MAX}; use crate::utils::{RSocketResult, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -66,13 +67,16 @@ impl RequestChannelBuilder { impl RequestChannel { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { - let n = bf.get_u32(); - let (m, d) = PayloadSupport::read(flag, bf); - Ok(RequestChannel { - initial_request_n: n, - metadata: m, - data: d, - }) + if bf.len() < 4 { + too_short(4) + } else { + let initial_request_n = bf.get_u32(); + read_payload(flag, bf).map(move |(metadata, data)| RequestChannel { + initial_request_n, + metadata, + data, + }) + } } pub fn builder(stream_id: u32, flag: u16) -> RequestChannelBuilder { diff --git a/rsocket/src/frame/request_fnf.rs b/rsocket/src/frame/request_fnf.rs index f88d2b4..bb952d2 100644 --- a/rsocket/src/frame/request_fnf.rs +++ b/rsocket/src/frame/request_fnf.rs @@ -1,3 +1,4 @@ +use super::utils::{read_payload, too_short}; use super::{Body, Frame, PayloadSupport}; use crate::utils::{RSocketResult, Writeable}; use bytes::{BufMut, Bytes, BytesMut}; @@ -59,8 +60,7 @@ impl RequestFNFBuilder { impl RequestFNF { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { - let (m, d) = PayloadSupport::read(flag, bf); - Ok(RequestFNF { + read_payload(flag, bf).map(|(m, d)| RequestFNF { metadata: m, data: d, }) diff --git a/rsocket/src/frame/request_n.rs b/rsocket/src/frame/request_n.rs index 2144187..c8000ed 100644 --- a/rsocket/src/frame/request_n.rs +++ b/rsocket/src/frame/request_n.rs @@ -1,3 +1,4 @@ +use super::utils::too_short; use super::{Body, Frame, REQUEST_MAX}; use crate::utils::{RSocketResult, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -34,8 +35,12 @@ impl RequestNBuilder { impl RequestN { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { - let n = bf.get_u32(); - Ok(RequestN { n }) + if bf.len() < 4 { + too_short(4) + } else { + let n = bf.get_u32(); + Ok(RequestN { n }) + } } pub fn builder(stream_id: u32, flag: u16) -> RequestNBuilder { diff --git a/rsocket/src/frame/request_response.rs b/rsocket/src/frame/request_response.rs index 1e8eb0a..8ace36b 100644 --- a/rsocket/src/frame/request_response.rs +++ b/rsocket/src/frame/request_response.rs @@ -1,3 +1,4 @@ +use super::utils::{read_payload, too_short}; use super::{Body, Frame, PayloadSupport}; use crate::utils::{RSocketResult, Writeable}; use bytes::{BufMut, Bytes, BytesMut}; @@ -59,8 +60,7 @@ impl RequestResponseBuilder { impl RequestResponse { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { - let (m, d) = PayloadSupport::read(flag, bf); - Ok(RequestResponse { + read_payload(flag, bf).map(|(m, d)| RequestResponse { metadata: m, data: d, }) diff --git a/rsocket/src/frame/request_stream.rs b/rsocket/src/frame/request_stream.rs index 9b2dd1a..59e2958 100644 --- a/rsocket/src/frame/request_stream.rs +++ b/rsocket/src/frame/request_stream.rs @@ -1,3 +1,4 @@ +use super::utils::{read_payload, too_short}; use super::{Body, Frame, PayloadSupport, REQUEST_MAX}; use crate::utils::{RSocketResult, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -54,13 +55,16 @@ impl RequestStreamBuilder { impl RequestStream { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { - let n = bf.get_u32(); - let (m, d) = PayloadSupport::read(flag, bf); - Ok(RequestStream { - initial_request_n: n, - metadata: m, - data: d, - }) + if bf.len() < 4 { + too_short(4) + } else { + let initial_request_n = bf.get_u32(); + read_payload(flag, bf).map(move |(metadata, data)| RequestStream { + initial_request_n, + metadata, + data, + }) + } } pub fn builder(stream_id: u32, flag: u16) -> RequestStreamBuilder { diff --git a/rsocket/src/frame/resume.rs b/rsocket/src/frame/resume.rs index 4898449..164a3c6 100644 --- a/rsocket/src/frame/resume.rs +++ b/rsocket/src/frame/resume.rs @@ -1,3 +1,4 @@ +use super::utils::too_short; use super::{Body, Frame, Version}; use crate::utils::{RSocketResult, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -27,21 +28,30 @@ impl Resume { } pub(crate) fn decode(flag: u16, b: &mut BytesMut) -> RSocketResult { + if b.len() < 6 { + return too_short(6); + } let major = b.get_u16(); let minor = b.get_u16(); - let token_size = b.get_u16(); + let token_size = b.get_u16() as usize; let token = if token_size > 0 { - Some(b.split_to(token_size as usize).to_bytes()) + if b.len() < token_size { + return too_short(token_size); + } + Some(b.split_to(token_size).freeze()) } else { None }; - let p1 = b.get_u64(); - let p2 = b.get_u64(); + if b.len() < 16 { + return too_short(16); + } + let last_received_server_position = b.get_u64(); + let first_available_client_position = b.get_u64(); Ok(Resume { version: Version::new(major, minor), token, - last_received_server_position: p1, - first_available_client_position: p2, + last_received_server_position, + first_available_client_position, }) } diff --git a/rsocket/src/frame/resume_ok.rs b/rsocket/src/frame/resume_ok.rs index a02a525..1dd2d1e 100644 --- a/rsocket/src/frame/resume_ok.rs +++ b/rsocket/src/frame/resume_ok.rs @@ -1,3 +1,4 @@ +use super::utils::too_short; use super::{Body, Frame}; use crate::utils::{RSocketResult, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -33,8 +34,13 @@ impl ResumeOKBuilder { impl ResumeOK { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { - let position = bf.get_u64(); - Ok(ResumeOK { position }) + if bf.len() < 8 { + too_short(8) + } else { + Ok(ResumeOK { + position: bf.get_u64(), + }) + } } pub fn builder(stream_id: u32, flag: u16) -> ResumeOKBuilder { diff --git a/rsocket/src/frame/setup.rs b/rsocket/src/frame/setup.rs index f1e0975..1020c2c 100644 --- a/rsocket/src/frame/setup.rs +++ b/rsocket/src/frame/setup.rs @@ -1,3 +1,4 @@ +use super::utils::{read_payload, too_short}; use super::{Body, Frame, PayloadSupport, Version}; use crate::utils::{RSocketResult, Writeable, DEFAULT_MIME_TYPE}; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -23,23 +24,45 @@ pub struct SetupBuilder { impl Setup { pub(crate) fn decode(flag: u16, b: &mut BytesMut) -> RSocketResult { + // Check minimal length: version(4bytes) + keepalive(4bytes) + lifetime(4bytes) + if b.len() < 12 { + return too_short(12); + } let major = b.get_u16(); let minor = b.get_u16(); let keepalive = b.get_u32(); let lifetime = b.get_u32(); let token: Option = if flag & Frame::FLAG_RESUME != 0 { - let l = b.get_u16(); - Some(b.split_to(l as usize).freeze()) + if b.len() < 2 { + return too_short(2); + } + let token_length = b.get_u16() as usize; + if b.len() < token_length { + return too_short(token_length); + } + Some(b.split_to(token_length).freeze()) } else { None }; - let mut len_mime: usize = b[0] as usize; + if b.is_empty() { + return too_short(1); + } + let mut mime_type_length: usize = b[0] as usize; b.advance(1); - let mime_metadata = b.split_to(len_mime).freeze(); - len_mime = b[0] as usize; + if b.len() < mime_type_length { + return too_short(mime_type_length); + } + let mime_metadata = b.split_to(mime_type_length).freeze(); + if b.is_empty() { + return too_short(1); + } + mime_type_length = b[0] as usize; b.advance(1); - let mime_data = b.split_to(len_mime).freeze(); - let (metadata, data) = PayloadSupport::read(flag, b); + if b.len() < mime_type_length { + return too_short(mime_type_length); + } + let mime_data = b.split_to(mime_type_length).freeze(); + let (metadata, data) = read_payload(flag, b)?; Ok(Setup { version: Version::new(major, minor), keepalive, diff --git a/rsocket/src/frame/utils.rs b/rsocket/src/frame/utils.rs index 7e4d38b..6b765eb 100644 --- a/rsocket/src/frame/utils.rs +++ b/rsocket/src/frame/utils.rs @@ -1,7 +1,29 @@ use super::Frame; -use crate::utils::{u24, Writeable}; +use crate::error::{ErrorKind, RSocketError}; +use crate::utils::{u24, RSocketResult, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; +pub(crate) fn read_payload( + flag: u16, + bf: &mut BytesMut, +) -> RSocketResult<(Option, Option)> { + let m: Option = if flag & Frame::FLAG_METADATA != 0 { + if bf.len() < 3 { + return too_short(3); + } + let n = u24::read_advance(bf); + Some(bf.split_to(n.into()).freeze()) + } else { + None + }; + let d: Option = if bf.is_empty() { + None + } else { + Some(Bytes::from(bf.to_vec())) + }; + Ok((m, d)) +} + pub(crate) struct PayloadSupport {} impl PayloadSupport { @@ -17,21 +39,6 @@ impl PayloadSupport { a + b } - pub fn read(flag: u16, bf: &mut BytesMut) -> (Option, Option) { - let m: Option = if flag & Frame::FLAG_METADATA != 0 { - let n = u24::read_advance(bf); - Some(bf.split_to(n.into()).freeze()) - } else { - None - }; - let d: Option = if bf.is_empty() { - None - } else { - Some(Bytes::from(bf.to_vec())) - }; - (m, d) - } - pub fn write(bf: &mut BytesMut, metadata: Option<&Bytes>, data: Option<&Bytes>) { if let Some(v) = metadata { u24::from(v.len()).write_to(bf); @@ -42,3 +49,7 @@ impl PayloadSupport { } } } + +pub(crate) fn too_short(n: usize) -> RSocketResult { + Err(ErrorKind::LengthTooShort(n).into()) +} From d90ef923ca768daeb281f97c66e1a025147a1df1 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Thu, 21 May 2020 23:08:50 +0800 Subject: [PATCH 11/70] 1. Optimize some codes. 2. Add qps benchmark. --- examples/Cargo.toml | 10 +++-- examples/qps.rs | 61 ++++++++++++++++++++++++++ rsocket-benchmark/Cargo.toml | 2 +- rsocket-messaging/Cargo.toml | 2 +- rsocket-test/tests/test_clients.rs | 10 ++--- rsocket-transport-tcp/Cargo.toml | 2 +- rsocket-transport-tcp/src/client.rs | 27 +++++++++--- rsocket-transport-wasm/src/runtime.rs | 2 +- rsocket-transport-websocket/Cargo.toml | 2 +- rsocket/Cargo.toml | 2 +- rsocket/src/extension/composite.rs | 4 +- rsocket/src/extension/routing.rs | 7 +-- rsocket/src/frame/mod.rs | 1 - rsocket/src/frame/payload.rs | 10 ++--- rsocket/src/frame/request_channel.rs | 12 ++--- rsocket/src/frame/request_fnf.rs | 9 ++-- rsocket/src/frame/request_n.rs | 5 +-- rsocket/src/frame/request_response.rs | 9 ++-- rsocket/src/frame/request_stream.rs | 11 +++-- rsocket/src/frame/setup.rs | 10 ++--- rsocket/src/frame/utils.rs | 30 ++++--------- rsocket/src/payload/setup.rs | 1 - rsocket/src/runtime/mod.rs | 2 +- rsocket/src/transport/fragmentation.rs | 4 +- rsocket/src/transport/socket.rs | 23 ++++------ rsocket/src/x/client.rs | 11 +++-- rsocket/src/x/server.rs | 5 +-- 27 files changed, 162 insertions(+), 112 deletions(-) create mode 100644 examples/qps.rs diff --git a/examples/Cargo.toml b/examples/Cargo.toml index c51e88a..1ba1217 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -9,7 +9,7 @@ publish = false log = "0.4.8" env_logger = "0.7.1" futures = "0.3.5" -clap = "2.33.0" +clap = "2.33.1" [dev-dependencies.rsocket_rust] path = "../rsocket" @@ -21,7 +21,7 @@ path = "../rsocket-transport-tcp" path = "../rsocket-transport-websocket" [dev-dependencies.tokio] -version = "0.2.20" +version = "0.2.21" default-features = false features = ["full"] @@ -35,4 +35,8 @@ path = "proxy.rs" [[example]] name = "cli" -path = "cli.rs" \ No newline at end of file +path = "cli.rs" + +[[example]] +name = "qps" +path = "qps.rs" diff --git a/examples/qps.rs b/examples/qps.rs new file mode 100644 index 0000000..c18053e --- /dev/null +++ b/examples/qps.rs @@ -0,0 +1,61 @@ +#[macro_use] +extern crate log; + +use rsocket_rust::prelude::*; +use rsocket_rust_transport_tcp::TcpClientTransport; +use std::error::Error; +use std::sync::{ + atomic::{AtomicU32, Ordering}, + Arc, +}; +use std::time::SystemTime; +use tokio::runtime::Runtime; +use tokio::sync::Notify; + +const TOTAL: u32 = 1_000_000; + +fn main() -> Result<(), Box> { + env_logger::builder().format_timestamp_millis().init(); + + let mut rt = Runtime::new()?; + let client = rt.block_on(async { + RSocketFactory::connect() + .transport(TcpClientTransport::from("127.0.0.1:7878")) + .start() + .await + })?; + // simulate 1KB payload. + let req = Payload::builder() + .set_data_utf8("X".repeat(1024).as_ref()) + .build(); + let counter = Arc::new(AtomicU32::new(0)); + let start_time = SystemTime::now(); + let notify = Arc::new(Notify::new()); + for _ in 0..TOTAL { + let client = client.clone(); + let counter = counter.clone(); + let notify = notify.clone(); + let req = req.clone(); + rt.spawn(async move { + client.request_response(req).await.expect("Request failed"); + let current = counter.fetch_add(1, Ordering::SeqCst) + 1; + if current >= TOTAL { + notify.notify(); + } + }); + } + rt.block_on(async move { + notify.notified().await; + }); + let costs = SystemTime::now() + .duration_since(start_time) + .unwrap() + .as_millis(); + info!( + "total={}, cost={}ms, qps={}", + TOTAL, + costs, + 1000f64 * (TOTAL as f64) / (costs as f64) + ); + Ok(()) +} diff --git a/rsocket-benchmark/Cargo.toml b/rsocket-benchmark/Cargo.toml index 1572750..d204b1c 100644 --- a/rsocket-benchmark/Cargo.toml +++ b/rsocket-benchmark/Cargo.toml @@ -30,7 +30,7 @@ path = "../rsocket-transport-websocket" path = "../rsocket-messaging" [dev-dependencies.tokio] -version = "0.2.20" +version = "0.2.21" default-features = false features = ["full"] diff --git a/rsocket-messaging/Cargo.toml b/rsocket-messaging/Cargo.toml index 575fcd0..99a0998 100644 --- a/rsocket-messaging/Cargo.toml +++ b/rsocket-messaging/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_messaging" -version = "0.1.0" +version = "0.5.2" authors = ["Jeffsky "] edition = "2018" diff --git a/rsocket-test/tests/test_clients.rs b/rsocket-test/tests/test_clients.rs index e020427..e024e48 100644 --- a/rsocket-test/tests/test_clients.rs +++ b/rsocket-test/tests/test_clients.rs @@ -146,7 +146,7 @@ async fn test_request_response_err() { async fn exec_request_response(socket: &Client) where - R: Send + Sync + Clone + Spawner + 'static, + R: Send + Sync + Copy + Spawner + 'static, { // request response let sending = Payload::builder() @@ -159,7 +159,7 @@ where async fn exec_metadata_push(socket: &Client) where - R: Send + Sync + Clone + Spawner + 'static, + R: Send + Sync + Copy + Spawner + 'static, { let pa = Payload::builder().set_metadata_utf8("Hello World!").build(); // metadata push @@ -168,7 +168,7 @@ where async fn exec_fire_and_forget(socket: &Client) where - R: Send + Sync + Clone + Spawner + 'static, + R: Send + Sync + Copy + Spawner + 'static, { // request fnf let fnf = Payload::from("Hello World!"); @@ -177,7 +177,7 @@ where async fn exec_request_stream(socket: &Client) where - R: Send + Sync + Clone + Spawner + 'static, + R: Send + Sync + Copy + Spawner + 'static, { // request stream let sending = Payload::builder() @@ -197,7 +197,7 @@ where async fn exec_request_channel(socket: &Client) where - R: Send + Sync + Clone + Spawner + 'static, + R: Send + Sync + Copy + Spawner + 'static, { let sends: Vec<_> = (0..10) .map(|n| { diff --git a/rsocket-transport-tcp/Cargo.toml b/rsocket-transport-tcp/Cargo.toml index 5c2762a..aeecbaf 100644 --- a/rsocket-transport-tcp/Cargo.toml +++ b/rsocket-transport-tcp/Cargo.toml @@ -19,7 +19,7 @@ path = "../rsocket" features = ["frame"] [dependencies.tokio] -version = "0.2.20" +version = "0.2.21" default-features = false features = [ "rt-core", "rt-threaded", "tcp", "sync", "stream" ] diff --git a/rsocket-transport-tcp/src/client.rs b/rsocket-transport-tcp/src/client.rs index e6aba44..e6ff764 100644 --- a/rsocket-transport-tcp/src/client.rs +++ b/rsocket-transport-tcp/src/client.rs @@ -4,8 +4,8 @@ use rsocket_rust::error::RSocketError; use rsocket_rust::frame::Frame; use rsocket_rust::runtime::{DefaultSpawner, Spawner}; use rsocket_rust::transport::{ClientTransport, Rx, Tx, TxOnce}; -use std::net::SocketAddr; -use std::net::TcpStream as StdTcpStream; +use std::net::{AddrParseError, SocketAddr, TcpStream as StdTcpStream}; +use std::str::FromStr; use tokio::net::TcpStream; use tokio_util::codec::Framed; @@ -75,6 +75,19 @@ impl ClientTransport for TcpClientTransport { } } +impl FromStr for TcpClientTransport { + type Err = AddrParseError; + + fn from_str(addr: &str) -> Result { + let socket_addr = if addr.starts_with("tcp://") || addr.starts_with("TCP://") { + addr.chars().skip(6).collect::().parse()? + } else { + addr.parse()? + }; + Ok(TcpClientTransport::new(Connector::Lazy(socket_addr))) + } +} + impl From for TcpClientTransport { fn from(addr: SocketAddr) -> TcpClientTransport { TcpClientTransport::new(Connector::Lazy(addr)) @@ -83,12 +96,12 @@ impl From for TcpClientTransport { impl From<&str> for TcpClientTransport { fn from(addr: &str) -> TcpClientTransport { - let socket_addr: SocketAddr = if addr.starts_with("tcp://") { - let ss: String = addr.chars().skip(6).collect(); - ss.parse().unwrap() + let socket_addr: SocketAddr = if addr.starts_with("tcp://") || addr.starts_with("TCP://") { + addr.chars().skip(6).collect::().parse() } else { - addr.parse().unwrap() - }; + addr.parse() + } + .expect("Invalid transport string!"); TcpClientTransport::new(Connector::Lazy(socket_addr)) } } diff --git a/rsocket-transport-wasm/src/runtime.rs b/rsocket-transport-wasm/src/runtime.rs index be260ce..4b39ae6 100644 --- a/rsocket-transport-wasm/src/runtime.rs +++ b/rsocket-transport-wasm/src/runtime.rs @@ -2,7 +2,7 @@ use rsocket_rust::runtime::Spawner; use std::future::Future; use wasm_bindgen_futures::spawn_local; -#[derive(Clone)] +#[derive(Clone, Copy, Debug)] pub struct WASMSpawner; impl Spawner for WASMSpawner { diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index 631f5bc..e4f7e6b 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -21,6 +21,6 @@ path = "../rsocket" features = ["frame"] [dependencies.tokio] -version = "0.2.20" +version = "0.2.21" default-features = false features = [ "rt-core", "rt-threaded", "tcp", "sync", "stream" ] diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index b350f20..07738a5 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -16,7 +16,7 @@ futures = "0.3.5" lazy_static = "1.4.0" [dependencies.tokio] -version = "0.2.20" +version = "0.2.21" default-features = false features = [ "rt-core", "rt-threaded", "sync", "stream" ] diff --git a/rsocket/src/extension/composite.rs b/rsocket/src/extension/composite.rs index e766da7..4398c9c 100644 --- a/rsocket/src/extension/composite.rs +++ b/rsocket/src/extension/composite.rs @@ -189,9 +189,7 @@ impl Writeable for CompositeMetadataEntry { MimeType::Normal(s) => { // NotWellKnown let mime_type_len = s.len() as u8; - if mime_type_len == 0 { - panic!("invalid length of MimeType!") - } + assert!(mime_type_len > 0, "invalid length of MimeType!"); bf.put_u8(mime_type_len - 1); bf.put_slice(s.as_ref()); } diff --git a/rsocket/src/extension/routing.rs b/rsocket/src/extension/routing.rs index 30cc349..5afe600 100644 --- a/rsocket/src/extension/routing.rs +++ b/rsocket/src/extension/routing.rs @@ -18,9 +18,10 @@ impl RoutingMetadataBuilder { self.push(String::from(tag)) } pub fn push(mut self, tag: String) -> Self { - if tag.len() > MAX_ROUTING_TAG_LEN { - panic!("exceeded maximum routing tag length!"); - } + assert!( + tag.len() <= MAX_ROUTING_TAG_LEN, + "exceeded maximum routing tag length!" + ); self.inner.tags.push(tag); self } diff --git a/rsocket/src/frame/mod.rs b/rsocket/src/frame/mod.rs index b0cfd4c..64ed12a 100644 --- a/rsocket/src/frame/mod.rs +++ b/rsocket/src/frame/mod.rs @@ -33,7 +33,6 @@ pub use request_stream::RequestStream; pub use resume::Resume; pub use resume_ok::ResumeOK; pub use setup::{Setup, SetupBuilder}; -pub use utils::*; pub use version::Version; pub const REQUEST_MAX: u32 = 0x7FFF_FFFF; // 2147483647 diff --git a/rsocket/src/frame/payload.rs b/rsocket/src/frame/payload.rs index 20a7ec8..8ff6b3f 100644 --- a/rsocket/src/frame/payload.rs +++ b/rsocket/src/frame/payload.rs @@ -1,5 +1,5 @@ -use super::utils::{read_payload, too_short}; -use super::{Body, Frame, PayloadSupport}; +use super::utils; +use super::{Body, Frame}; use crate::utils::{RSocketResult, Writeable}; use bytes::{BufMut, Bytes, BytesMut}; @@ -60,7 +60,7 @@ impl PayloadBuilder { impl Payload { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { - read_payload(flag, bf).map(|(metadata, data)| Payload { metadata, data }) + utils::read_payload(flag, bf).map(|(metadata, data)| Payload { metadata, data }) } pub fn builder(stream_id: u32, flag: u16) -> PayloadBuilder { @@ -88,10 +88,10 @@ impl Payload { impl Writeable for Payload { fn write_to(&self, bf: &mut BytesMut) { - PayloadSupport::write(bf, self.get_metadata(), self.get_data()); + utils::write_payload(bf, self.get_metadata(), self.get_data()); } fn len(&self) -> usize { - PayloadSupport::len(self.get_metadata(), self.get_data()) + utils::calculate_payload_length(self.get_metadata(), self.get_data()) } } diff --git a/rsocket/src/frame/request_channel.rs b/rsocket/src/frame/request_channel.rs index 67f80bf..82e5c5c 100644 --- a/rsocket/src/frame/request_channel.rs +++ b/rsocket/src/frame/request_channel.rs @@ -1,5 +1,5 @@ -use super::utils::{read_payload, too_short}; -use super::{Body, Frame, PayloadSupport, REQUEST_MAX}; +use super::utils; +use super::{Body, Frame, REQUEST_MAX}; use crate::utils::{RSocketResult, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -68,10 +68,10 @@ impl RequestChannelBuilder { impl RequestChannel { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { if bf.len() < 4 { - too_short(4) + utils::too_short(4) } else { let initial_request_n = bf.get_u32(); - read_payload(flag, bf).map(move |(metadata, data)| RequestChannel { + utils::read_payload(flag, bf).map(move |(metadata, data)| RequestChannel { initial_request_n, metadata, data, @@ -108,10 +108,10 @@ impl RequestChannel { impl Writeable for RequestChannel { fn write_to(&self, bf: &mut BytesMut) { bf.put_u32(self.initial_request_n); - PayloadSupport::write(bf, self.get_metadata(), self.get_data()); + utils::write_payload(bf, self.get_metadata(), self.get_data()); } fn len(&self) -> usize { - 4 + PayloadSupport::len(self.get_metadata(), self.get_data()) + 4 + utils::calculate_payload_length(self.get_metadata(), self.get_data()) } } diff --git a/rsocket/src/frame/request_fnf.rs b/rsocket/src/frame/request_fnf.rs index bb952d2..b4a26cc 100644 --- a/rsocket/src/frame/request_fnf.rs +++ b/rsocket/src/frame/request_fnf.rs @@ -1,5 +1,4 @@ -use super::utils::{read_payload, too_short}; -use super::{Body, Frame, PayloadSupport}; +use super::{utils, Body, Frame}; use crate::utils::{RSocketResult, Writeable}; use bytes::{BufMut, Bytes, BytesMut}; @@ -60,7 +59,7 @@ impl RequestFNFBuilder { impl RequestFNF { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { - read_payload(flag, bf).map(|(m, d)| RequestFNF { + utils::read_payload(flag, bf).map(|(m, d)| RequestFNF { metadata: m, data: d, }) @@ -91,10 +90,10 @@ impl RequestFNF { impl Writeable for RequestFNF { fn write_to(&self, bf: &mut BytesMut) { - PayloadSupport::write(bf, self.get_metadata(), self.get_data()); + utils::write_payload(bf, self.get_metadata(), self.get_data()); } fn len(&self) -> usize { - PayloadSupport::len(self.get_metadata(), self.get_data()) + utils::calculate_payload_length(self.get_metadata(), self.get_data()) } } diff --git a/rsocket/src/frame/request_n.rs b/rsocket/src/frame/request_n.rs index c8000ed..db59fc7 100644 --- a/rsocket/src/frame/request_n.rs +++ b/rsocket/src/frame/request_n.rs @@ -1,5 +1,4 @@ -use super::utils::too_short; -use super::{Body, Frame, REQUEST_MAX}; +use super::{utils, Body, Frame, REQUEST_MAX}; use crate::utils::{RSocketResult, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -36,7 +35,7 @@ impl RequestNBuilder { impl RequestN { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { if bf.len() < 4 { - too_short(4) + utils::too_short(4) } else { let n = bf.get_u32(); Ok(RequestN { n }) diff --git a/rsocket/src/frame/request_response.rs b/rsocket/src/frame/request_response.rs index 8ace36b..0d3b4d9 100644 --- a/rsocket/src/frame/request_response.rs +++ b/rsocket/src/frame/request_response.rs @@ -1,5 +1,4 @@ -use super::utils::{read_payload, too_short}; -use super::{Body, Frame, PayloadSupport}; +use super::{utils, Body, Frame}; use crate::utils::{RSocketResult, Writeable}; use bytes::{BufMut, Bytes, BytesMut}; @@ -60,7 +59,7 @@ impl RequestResponseBuilder { impl RequestResponse { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { - read_payload(flag, bf).map(|(m, d)| RequestResponse { + utils::read_payload(flag, bf).map(|(m, d)| RequestResponse { metadata: m, data: d, }) @@ -91,10 +90,10 @@ impl RequestResponse { impl Writeable for RequestResponse { fn write_to(&self, bf: &mut BytesMut) { - PayloadSupport::write(bf, self.get_metadata(), self.get_data()) + utils::write_payload(bf, self.get_metadata(), self.get_data()) } fn len(&self) -> usize { - PayloadSupport::len(self.get_metadata(), self.get_data()) + utils::calculate_payload_length(self.get_metadata(), self.get_data()) } } diff --git a/rsocket/src/frame/request_stream.rs b/rsocket/src/frame/request_stream.rs index 59e2958..23412ed 100644 --- a/rsocket/src/frame/request_stream.rs +++ b/rsocket/src/frame/request_stream.rs @@ -1,5 +1,4 @@ -use super::utils::{read_payload, too_short}; -use super::{Body, Frame, PayloadSupport, REQUEST_MAX}; +use super::{utils, Body, Frame, REQUEST_MAX}; use crate::utils::{RSocketResult, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -56,10 +55,10 @@ impl RequestStreamBuilder { impl RequestStream { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { if bf.len() < 4 { - too_short(4) + utils::too_short(4) } else { let initial_request_n = bf.get_u32(); - read_payload(flag, bf).map(move |(metadata, data)| RequestStream { + utils::read_payload(flag, bf).map(move |(metadata, data)| RequestStream { initial_request_n, metadata, data, @@ -105,10 +104,10 @@ impl RequestStream { impl Writeable for RequestStream { fn write_to(&self, bf: &mut BytesMut) { bf.put_u32(self.initial_request_n); - PayloadSupport::write(bf, self.get_metadata(), self.get_data()) + utils::write_payload(bf, self.get_metadata(), self.get_data()) } fn len(&self) -> usize { - 4 + PayloadSupport::len(self.get_metadata(), self.get_data()) + 4 + utils::calculate_payload_length(self.get_metadata(), self.get_data()) } } diff --git a/rsocket/src/frame/setup.rs b/rsocket/src/frame/setup.rs index 1020c2c..a163cdc 100644 --- a/rsocket/src/frame/setup.rs +++ b/rsocket/src/frame/setup.rs @@ -1,5 +1,5 @@ -use super::utils::{read_payload, too_short}; -use super::{Body, Frame, PayloadSupport, Version}; +use super::utils::{self, too_short}; +use super::{Body, Frame, Version}; use crate::utils::{RSocketResult, Writeable, DEFAULT_MIME_TYPE}; use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::time::Duration; @@ -62,7 +62,7 @@ impl Setup { return too_short(mime_type_length); } let mime_data = b.split_to(mime_type_length).freeze(); - let (metadata, data) = read_payload(flag, b)?; + let (metadata, data) = utils::read_payload(flag, b)?; Ok(Setup { version: Version::new(major, minor), keepalive, @@ -133,7 +133,7 @@ impl Writeable for Setup { None => 0, }; n += 2 + self.mime_metadata.len() + self.mime_data.len(); - n += PayloadSupport::len(self.get_metadata(), self.get_data()); + n += utils::calculate_payload_length(self.get_metadata(), self.get_data()); n } @@ -149,7 +149,7 @@ impl Writeable for Setup { bf.put(self.mime_metadata.clone()); bf.put_u8(self.mime_data.len() as u8); bf.put(self.mime_data.clone()); - PayloadSupport::write(bf, self.get_metadata(), self.get_data()); + utils::write_payload(bf, self.get_metadata(), self.get_data()); } } diff --git a/rsocket/src/frame/utils.rs b/rsocket/src/frame/utils.rs index 6b765eb..448ce34 100644 --- a/rsocket/src/frame/utils.rs +++ b/rsocket/src/frame/utils.rs @@ -24,29 +24,17 @@ pub(crate) fn read_payload( Ok((m, d)) } -pub(crate) struct PayloadSupport {} +pub(crate) fn calculate_payload_length(metadata: Option<&Bytes>, data: Option<&Bytes>) -> usize { + metadata.map(|v| 3 + v.len()).unwrap_or(0) + data.map(|v| v.len()).unwrap_or(0) +} -impl PayloadSupport { - pub fn len(metadata: Option<&Bytes>, data: Option<&Bytes>) -> usize { - let a = match metadata { - Some(v) => 3 + v.len(), - None => 0, - }; - let b = match data { - Some(v) => v.len(), - None => 0, - }; - a + b +pub(crate) fn write_payload(bf: &mut BytesMut, metadata: Option<&Bytes>, data: Option<&Bytes>) { + if let Some(v) = metadata { + u24::from(v.len()).write_to(bf); + bf.put(v.clone()); } - - pub fn write(bf: &mut BytesMut, metadata: Option<&Bytes>, data: Option<&Bytes>) { - if let Some(v) = metadata { - u24::from(v.len()).write_to(bf); - bf.put(v.clone()); - } - if let Some(v) = data { - bf.put(v.clone()) - } + if let Some(v) = data { + bf.put(v.clone()) } } diff --git a/rsocket/src/payload/setup.rs b/rsocket/src/payload/setup.rs index a070b3b..1db9498 100644 --- a/rsocket/src/payload/setup.rs +++ b/rsocket/src/payload/setup.rs @@ -145,7 +145,6 @@ impl From for SetupPayload { // TODO: fill other properties. bu = bu.set_data_mime_type(input.get_mime_data()); bu = bu.set_metadata_mime_type(input.get_mime_metadata()); - // bu.set_data_mime_type(String::input.get_mime_data()); let ka = (input.get_keepalive(), input.get_lifetime()); let (d, m) = input.split(); bu.inner.d = d; diff --git a/rsocket/src/runtime/mod.rs b/rsocket/src/runtime/mod.rs index fab2709..d5dd24f 100644 --- a/rsocket/src/runtime/mod.rs +++ b/rsocket/src/runtime/mod.rs @@ -6,7 +6,7 @@ pub trait Spawner { F: Send + Future + 'static; } -#[derive(Clone)] +#[derive(Clone, Copy, Debug)] pub struct DefaultSpawner; impl Spawner for DefaultSpawner { diff --git a/rsocket/src/transport/fragmentation.rs b/rsocket/src/transport/fragmentation.rs index e319497..3388549 100644 --- a/rsocket/src/transport/fragmentation.rs +++ b/rsocket/src/transport/fragmentation.rs @@ -16,9 +16,7 @@ pub(crate) struct Splitter { impl Splitter { pub(crate) fn new(mtu: usize) -> Splitter { - if mtu <= frame::LEN_HEADER { - panic!("mtu is too small!") - } + assert!(mtu > frame::LEN_HEADER, "mtu is too small!"); Splitter { mtu } } diff --git a/rsocket/src/transport/socket.rs b/rsocket/src/transport/socket.rs index 274c9dd..3e5634b 100644 --- a/rsocket/src/transport/socket.rs +++ b/rsocket/src/transport/socket.rs @@ -21,10 +21,7 @@ use tokio::prelude::*; use tokio::sync::Mutex; #[derive(Clone)] -pub(crate) struct DuplexSocket -where - R: Send + Sync + Clone + Spawner + 'static, -{ +pub(crate) struct DuplexSocket { rt: R, seq: StreamID, responder: Responder, @@ -50,7 +47,7 @@ enum Handler { impl DuplexSocket where - R: Send + Sync + Clone + Spawner + 'static, + R: Send + Sync + Copy + Spawner + 'static, { pub(crate) async fn new( rt: R, @@ -58,7 +55,6 @@ where tx: Tx, splitter: Option, ) -> DuplexSocket { - let rt2 = rt.clone(); let (canceller_tx, canceller_rx) = new_tx_rx::(); let handlers = [ Arc::new(Mutex::new(HashMap::new())), @@ -78,7 +74,7 @@ where Arc::new(Mutex::new(HashMap::new())), Arc::new(Mutex::new(HashMap::new())), ]; - let ds = DuplexSocket { + let duplex_socket = DuplexSocket { rt, seq: StreamID::from(first_stream_id), tx, @@ -89,11 +85,11 @@ where splitter, }; - let ds2 = ds.clone(); - rt2.spawn(async move { - ds2.loop_canceller(canceller_rx).await; + let cloned_duplex_socket = duplex_socket.clone(); + rt.spawn(async move { + cloned_duplex_socket.loop_canceller(canceller_rx).await; }); - ds + duplex_socket } pub(crate) fn close(self) { @@ -673,7 +669,7 @@ where impl RSocket for DuplexSocket where - R: Send + Sync + Clone + Spawner + 'static, + R: Send + Sync + Copy + Spawner + 'static, { fn metadata_push(&self, req: Payload) -> Mono<()> { let sid = self.seq.next(); @@ -959,8 +955,7 @@ impl Responder { } fn set(&self, rs: Box) { - let inner = self.inner.clone(); - let mut v = inner.write().unwrap(); + let mut v = self.inner.write().unwrap(); *v = rs; } } diff --git a/rsocket/src/x/client.rs b/rsocket/src/x/client.rs index 4556b19..8f7a617 100644 --- a/rsocket/src/x/client.rs +++ b/rsocket/src/x/client.rs @@ -18,7 +18,7 @@ use std::time::Duration; #[derive(Clone)] pub struct Client where - R: Send + Sync + Clone + Spawner + 'static, + R: Send + Sync + Copy + Spawner + 'static, { socket: DuplexSocket, } @@ -115,10 +115,9 @@ where rt: R, ) -> Result, Box> where - R: Send + Sync + Clone + Spawner + 'static, + R: Send + Sync + Copy + Spawner + 'static, { let tp = self.transport.take().expect("missint transport"); - let cloned_rt = rt.clone(); let (rcv_tx, rcv_rx) = mpsc::unbounded::(); let (snd_tx, snd_rx) = mpsc::unbounded::(); let (connected_tx, connected_rx) = oneshot::channel::>(); @@ -136,7 +135,7 @@ where None => None, }; let closer = self.closer.take(); - cloned_rt.spawn(async move { + rt.spawn(async move { cloned_duplex_socket.event_loop(acceptor, rcv_rx).await; if let Some(mut invoke) = closer { invoke(); @@ -150,7 +149,7 @@ where impl Client where - R: Send + Sync + Clone + Spawner + 'static, + R: Send + Sync + Copy + Spawner + 'static, { fn new(socket: DuplexSocket) -> Client { Client { socket } @@ -163,7 +162,7 @@ where impl RSocket for Client where - R: Send + Sync + Clone + Spawner + 'static, + R: Send + Sync + Copy + Spawner + 'static, { fn metadata_push(&self, req: Payload) -> Mono<()> { self.socket.metadata_push(req) diff --git a/rsocket/src/x/server.rs b/rsocket/src/x/server.rs index e392051..d6b28f9 100644 --- a/rsocket/src/x/server.rs +++ b/rsocket/src/x/server.rs @@ -66,7 +66,7 @@ where pub async fn serve_with_runtime(mut self, rt: R) -> Result<(), Box> where - R: Send + Sync + Clone + Spawner + 'static, + R: Send + Sync + Copy + Spawner + 'static, { let tp = self.transport.take().expect("missing transport"); let starter = self.start_handler; @@ -78,7 +78,6 @@ where let mtu = self.mtu; tp.start(starter, move |tp| { - let cloned_rt = rt.clone(); let (rcv_tx, rcv_rx) = mpsc::unbounded::(); let (snd_tx, snd_rx) = mpsc::unbounded::(); tp.attach(rcv_tx, snd_rx, None); @@ -90,7 +89,7 @@ where } else { Some(Splitter::new(mtu)) }; - let ds = DuplexSocket::new(cloned_rt, 0, snd_tx, splitter).await; + let ds = DuplexSocket::new(rt, 0, snd_tx, splitter).await; ds.event_loop(acceptor, rcv_rx).await; }); }) From 4516102298845ab8c954811b3233a89997e19657 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Mon, 25 May 2020 22:56:15 +0800 Subject: [PATCH 12/70] optimize setup data and metadata for messaging requester. --- rsocket-messaging/Cargo.toml | 2 - rsocket-messaging/src/lib.rs | 5 -- rsocket-messaging/src/misc.rs | 16 ++-- rsocket-messaging/src/requester.rs | 116 +++++++++++---------------- rsocket-test/tests/test_messaging.rs | 8 +- 5 files changed, 60 insertions(+), 87 deletions(-) diff --git a/rsocket-messaging/Cargo.toml b/rsocket-messaging/Cargo.toml index 99a0998..42533d2 100644 --- a/rsocket-messaging/Cargo.toml +++ b/rsocket-messaging/Cargo.toml @@ -5,10 +5,8 @@ authors = ["Jeffsky "] edition = "2018" [dependencies] -log = "0.4.8" futures = "0.3.5" bytes = "0.5.4" -lazy_static = "1.4.0" serde = "1.0.110" serde_json = "1.0.53" serde_cbor = "0.11.1" diff --git a/rsocket-messaging/src/lib.rs b/rsocket-messaging/src/lib.rs index c663c8a..5b9ec96 100644 --- a/rsocket-messaging/src/lib.rs +++ b/rsocket-messaging/src/lib.rs @@ -1,8 +1,3 @@ -#[macro_use] -extern crate log; -// #[macro_use] -// extern crate lazy_static; - mod misc; mod requester; diff --git a/rsocket-messaging/src/misc.rs b/rsocket-messaging/src/misc.rs index 974309c..18f9c44 100644 --- a/rsocket-messaging/src/misc.rs +++ b/rsocket-messaging/src/misc.rs @@ -2,12 +2,12 @@ use serde::{de::DeserializeOwned, Serialize}; use std::error::Error; pub trait SerDe { - fn marshal(&self, data: &T) -> Result, Box> + fn marshal(&self, data: &T) -> Result, Box> where Self: Sized, T: Sized + Serialize; - fn unmarshal(&self, raw: &[u8]) -> Result> + fn unmarshal(&self, raw: &[u8]) -> Result> where Self: Sized, T: Sized + DeserializeOwned; @@ -17,14 +17,14 @@ pub trait SerDe { struct JsonSerDe {} impl SerDe for JsonSerDe { - fn marshal(&self, data: &T) -> Result, Box> + fn marshal(&self, data: &T) -> Result, Box> where T: Sized + Serialize, { Ok(serde_json::to_vec(data)?) } - fn unmarshal(&self, raw: &[u8]) -> Result> + fn unmarshal(&self, raw: &[u8]) -> Result> where T: Sized + DeserializeOwned, { @@ -43,14 +43,14 @@ pub fn cbor() -> impl SerDe { struct CborSerDe {} impl SerDe for CborSerDe { - fn marshal(&self, data: &T) -> Result, Box> + fn marshal(&self, data: &T) -> Result, Box> where T: Sized + Serialize, { Ok(serde_cbor::to_vec(data)?) } - fn unmarshal(&self, raw: &[u8]) -> Result> + fn unmarshal(&self, raw: &[u8]) -> Result> where T: Sized + DeserializeOwned, { @@ -58,14 +58,14 @@ impl SerDe for CborSerDe { } } -pub(crate) fn marshal(ser: impl SerDe, data: &T) -> Result, Box> +pub(crate) fn marshal(ser: impl SerDe, data: &T) -> Result, Box> where T: Sized + Serialize, { ser.marshal(data) } -pub(crate) fn unmarshal(de: impl SerDe, raw: &[u8]) -> Result> +pub(crate) fn unmarshal(de: impl SerDe, raw: &[u8]) -> Result> where T: Sized + DeserializeOwned, { diff --git a/rsocket-messaging/src/requester.rs b/rsocket-messaging/src/requester.rs index fb69d82..b88262e 100644 --- a/rsocket-messaging/src/requester.rs +++ b/rsocket-messaging/src/requester.rs @@ -1,9 +1,7 @@ use super::misc::{self, marshal, unmarshal}; use bytes::{Bytes, BytesMut}; use rsocket_rust::error::RSocketError; -use rsocket_rust::extension::{ - CompositeMetadata, CompositeMetadataEntry, MimeType, RoutingMetadata, -}; +use rsocket_rust::extension::{CompositeMetadata, MimeType, RoutingMetadata}; use rsocket_rust::prelude::*; use rsocket_rust::utils::Writeable; use rsocket_rust_transport_tcp::TcpClientTransport; @@ -16,11 +14,13 @@ use std::result::Result; use std::sync::Arc; use url::Url; -type FnMetadata = Box Result<(MimeType, Vec), Box>>; -type FnData = Box Result, Box>>; -type PreflightResult = Result<(Payload, MimeType, Arc>), Box>; -type UnpackerResult = Result<(MimeType, Payload), RSocketError>; -type UnpackersResult = Result<(MimeType, Flux>), Box>; +type FnMetadata = Box Result<(MimeType, Vec), Box>>; +type FnData = Box Result, Box>>; +type PreflightResult = + Result<(Payload, MimeType, Arc>), Box>; +type UnpackerResult = Result<(MimeType, Payload), Box>; +type UnpackersResult = + Result<(MimeType, Flux>), Box>; enum TransportKind { TCP(String, u16), @@ -41,8 +41,8 @@ pub struct RequestSpec { pub struct RequesterBuilder { data_mime_type: Option, route: Option, - metadata: Vec, - data: Option>, + metadata: LinkedList, + data: Option, tp: Option, } @@ -83,40 +83,26 @@ impl RequesterBuilder { self } - pub fn setup_data(mut self, data: &D) -> Self + pub fn setup_data(mut self, data: D) -> Self where - D: Sized + Serialize, + D: Sized + Serialize + 'static, { - // TODO: lazy set - let result = match &self.data_mime_type { - Some(m) => do_marshal(m, data), - None => do_marshal(&MimeType::APPLICATION_JSON, data), - }; - match result { - Ok(raw) => { - self.data = Some(raw); - } - Err(e) => { - error!("marshal failed: {:?}", e); - } - } + self.data = Some(Box::new(move |mime_type: &MimeType| { + do_marshal(mime_type, &data) + })); self } - pub fn setup_metadata(mut self, metadata: &M, mime_type: T) -> Self + pub fn setup_metadata(mut self, metadata: M, mime_type: T) -> Self where - M: Sized + Serialize, + M: Sized + Serialize + 'static, T: Into, { - // TODO: lazy set let mime_type = mime_type.into(); - match do_marshal(&mime_type, metadata) { - Ok(raw) => { - let entry = CompositeMetadataEntry::new(mime_type, Bytes::from(raw)); - self.metadata.push(entry); - } - Err(e) => error!("marshal failed: {:?}", e), - } + self.metadata.push_back(Box::new(move || { + let raw = do_marshal(&mime_type, &metadata)?; + Ok((mime_type.clone(), raw)) + })); self } @@ -148,8 +134,10 @@ impl RequesterBuilder { composite_builder.push(MimeType::MESSAGE_X_RSOCKET_ROUTING_V0, routing.bytes()); added += 1; } - for it in self.metadata.into_iter() { - composite_builder = composite_builder.push_entry(it); + + for mut gen in self.metadata.into_iter() { + let (mime_type, raw) = gen()?; + composite_builder = composite_builder.push(mime_type, raw); added += 1; } @@ -159,8 +147,8 @@ impl RequesterBuilder { payload_builder = payload_builder.set_metadata(composite_builder.build()); } - if let Some(raw) = self.data { - payload_builder = payload_builder.set_data(raw); + if let Some(mut gen) = self.data { + payload_builder = payload_builder.set_data(gen(&data_mime_type)?); } let setup = payload_builder.build(); @@ -291,16 +279,12 @@ impl RequestSpec { Ok(v) => Unpacker { inner: Ok((mime_type, v)), }, - Err(e) => Unpacker { inner: Err(e) }, - } - } - Err(e) => { - // TODO: better error - let msg = format!("{}", e); - Unpacker { - inner: Err(RSocketError::from(msg)), + Err(e) => Unpacker { + inner: Err(e.into()), + }, } } + Err(e) => Unpacker { inner: Err(e) }, } } @@ -337,7 +321,7 @@ impl RequestSpec { } impl Unpackers { - pub async fn block(self) -> Result, Box> + pub async fn block(self) -> Result, Box> where T: Sized + DeserializeOwned, { @@ -353,12 +337,13 @@ impl Unpackers { } } } - Err(e) => return Err(format!("{}", e).into()), + Err(e) => return Err(e.into()), } } Ok(res) } - pub async fn foreach(self, callback: impl Fn(T)) -> Result<(), Box> + + pub async fn foreach(self, callback: impl Fn(T)) -> Result<(), Box> where T: Sized + DeserializeOwned, { @@ -381,39 +366,34 @@ impl Unpackers { } impl Unpacker { - pub fn block(self) -> Result, Box> + pub fn block(self) -> Result, Box> where T: Sized + DeserializeOwned, { - match self.inner { - Ok((mime_type, inner)) => match inner.data() { - // TODO: support more mime types. - Some(raw) => do_unmarshal(&mime_type, raw), - None => Ok(None), - }, - Err(e) => Err(format!("{}", e).into()), + let (mime_type, inner) = self.inner?; + match inner.data() { + Some(raw) => do_unmarshal(&mime_type, raw), + None => Ok(None), } } } -fn do_unmarshal(mime_type: &MimeType, raw: &Bytes) -> Result, Box> +fn do_unmarshal( + mime_type: &MimeType, + raw: &Bytes, +) -> Result, Box> where T: Sized + DeserializeOwned, { + // TODO: support more mime types match *mime_type { - MimeType::APPLICATION_JSON => { - let t = unmarshal(misc::json(), &raw.as_ref())?; - Ok(Some(t)) - } - MimeType::APPLICATION_CBOR => { - let t = unmarshal(misc::cbor(), &raw.as_ref())?; - Ok(Some(t)) - } + MimeType::APPLICATION_JSON => Ok(Some(unmarshal(misc::json(), &raw.as_ref())?)), + MimeType::APPLICATION_CBOR => Ok(Some(unmarshal(misc::cbor(), &raw.as_ref())?)), _ => Err("unsupported mime type!".into()), } } -fn do_marshal(mime_type: &MimeType, data: &T) -> Result, Box> +fn do_marshal(mime_type: &MimeType, data: &T) -> Result, Box> where T: Sized + Serialize, { diff --git a/rsocket-test/tests/test_messaging.rs b/rsocket-test/tests/test_messaging.rs index 4f1bde1..4d08e76 100644 --- a/rsocket-test/tests/test_messaging.rs +++ b/rsocket-test/tests/test_messaging.rs @@ -19,7 +19,7 @@ pub struct Token { access: String, } -#[derive(Serialize, Deserialize, Debug, Default, Clone)] +#[derive(Serialize, Deserialize, Debug, Default)] pub struct Student { id: i64, name: String, @@ -44,13 +44,13 @@ pub struct Response { #[ignore] async fn test_messaging() { init(); - let token = Token { + let token = || Token { app: "xxx".to_owned(), access: "yyy".to_owned(), }; let requester = Requester::builder() - .setup_metadata(&token, MimeType::APPLICATION_JSON) - .setup_data(&token) + .setup_metadata(token(), MimeType::APPLICATION_JSON) + .setup_data(token()) .connect_tcp("127.0.0.1", 7878) .build() .await From 2f434014dc4f4365b51ac36f9ed0638fac12fdb2 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Tue, 26 May 2020 22:38:47 +0800 Subject: [PATCH 13/70] prepare for release v0.5.2 --- rsocket-messaging/Cargo.toml | 11 +++- rsocket-messaging/README.md | 7 +++ rsocket-transport-tcp/Cargo.toml | 2 +- rsocket-transport-tcp/README.md | 82 ++++++++++++++++++++++++++ rsocket-transport-wasm/Cargo.toml | 4 +- rsocket-transport-wasm/README.md | 2 +- rsocket-transport-websocket/Cargo.toml | 2 +- rsocket-transport-websocket/README.md | 6 +- 8 files changed, 105 insertions(+), 11 deletions(-) create mode 100644 rsocket-messaging/README.md diff --git a/rsocket-messaging/Cargo.toml b/rsocket-messaging/Cargo.toml index 42533d2..ada8909 100644 --- a/rsocket-messaging/Cargo.toml +++ b/rsocket-messaging/Cargo.toml @@ -3,6 +3,11 @@ name = "rsocket_rust_messaging" version = "0.5.2" authors = ["Jeffsky "] edition = "2018" +license = "Apache-2.0" +readme = "README.md" +repository = "https://github.com/rsocket/rsocket-rust" +homepage = "https://github.com/rsocket/rsocket-rust" +description = "Communicate with Spring RSocket Messaging." [dependencies] futures = "0.3.5" @@ -14,11 +19,11 @@ hex = "0.4.2" url = "2.1.1" [dependencies.rsocket_rust] -path = "../rsocket" +version = "0.5.2" features = ["frame"] [dependencies.rsocket_rust_transport_tcp] -path = "../rsocket-transport-tcp" +version = "0.5.2" [dependencies.rsocket_rust_transport_websocket] -path = "../rsocket-transport-websocket" \ No newline at end of file +version = "0.5.2" diff --git a/rsocket-messaging/README.md b/rsocket-messaging/README.md new file mode 100644 index 0000000..221746b --- /dev/null +++ b/rsocket-messaging/README.md @@ -0,0 +1,7 @@ +# RSocket Messaging + +Communicate with Spring RSocket Messaging. + +## Example + +Here's a good example: [https://github.com/feuyeux/kio](https://github.com/feuyeux/kio). diff --git a/rsocket-transport-tcp/Cargo.toml b/rsocket-transport-tcp/Cargo.toml index aeecbaf..bbc7e0c 100644 --- a/rsocket-transport-tcp/Cargo.toml +++ b/rsocket-transport-tcp/Cargo.toml @@ -15,7 +15,7 @@ futures = "0.3.5" bytes = "0.5.4" [dependencies.rsocket_rust] -path = "../rsocket" +version = "0.5.2" features = ["frame"] [dependencies.tokio] diff --git a/rsocket-transport-tcp/README.md b/rsocket-transport-tcp/README.md index 0d70635..666e7c7 100644 --- a/rsocket-transport-tcp/README.md +++ b/rsocket-transport-tcp/README.md @@ -1 +1,83 @@ # RSocket Transport For TCP + +## Example + +Add dependencies in your `Cargo.toml`. + +```toml +[dependencies] +tokio = "0.2.21" +rsocket_rust = "0.5.2" +rsocket_rust_transport_tcp = "0.5.2" +``` + +### Server + +```rust +use log::info; +use rsocket_rust::prelude::{EchoRSocket, RSocketFactory, ServerResponder}; +use rsocket_rust_transport_tcp::TcpServerTransport; +use std::error::Error; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let transport: TcpServerTransport = TcpServerTransport::from("127.0.0.1:7878"); + + let responder: ServerResponder = Box::new(|setup, _socket| { + info!("accept setup: {:?}", setup); + Ok(Box::new(EchoRSocket)) + // Or you can reject setup + // Err(From::from("SETUP_NOT_ALLOW")) + }); + + let on_start: Box = + Box::new(|| info!("+++++++ echo server started! +++++++")); + + RSocketFactory::receive() + .transport(transport) + .acceptor(responder) + .on_start(on_start) + .serve() + .await?; + + Ok(()) +} + +``` + +### Client + +```rust +use log::info; +use rsocket_rust::prelude::{ClientResponder, EchoRSocket, Payload, RSocket, RSocketFactory}; +use rsocket_rust_transport_tcp::TcpClientTransport; +use std::error::Error; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let responder: ClientResponder = Box::new(|| Box::new(EchoRSocket)); + + let client = RSocketFactory::connect() + .acceptor(responder) + .transport(TcpClientTransport::from("127.0.0.1:7878")) + .setup(Payload::from("READY!")) + .mime_type("text/plain", "text/plain") + .start() + .await + .unwrap(); + + let request_payload: Payload = Payload::builder() + .set_data_utf8("Hello World!") + .set_metadata_utf8("Rust") + .build(); + + let res = client.request_response(request_payload).await.unwrap(); + + info!("got: {:?}", res); + + client.close(); + + Ok(()) +} + +``` diff --git a/rsocket-transport-wasm/Cargo.toml b/rsocket-transport-wasm/Cargo.toml index a230c84..ffc2844 100644 --- a/rsocket-transport-wasm/Cargo.toml +++ b/rsocket-transport-wasm/Cargo.toml @@ -19,7 +19,7 @@ serde = "1.0.110" serde_derive = "1.0.110" [dependencies.rsocket_rust] -path = "../rsocket" +version = "0.5.2" features = ["frame"] [dependencies.wasm-bindgen] @@ -27,7 +27,7 @@ version = "0.2.62" features = ["serde-serialize"] [dependencies.web-sys] -version = "0.3.37" +version = "0.3.39" features = [ "FileReader", "ProgressEvent", diff --git a/rsocket-transport-wasm/README.md b/rsocket-transport-wasm/README.md index 3a6e9bb..c72144a 100644 --- a/rsocket-transport-wasm/README.md +++ b/rsocket-transport-wasm/README.md @@ -7,7 +7,7 @@ See: [https://github.com/jjeffcaii/rsocket-rust-wasm-example](https://github.com ## TODO - [ ] MetadataPush -- [ ] FireAndForget +- [x] FireAndForget - [x] RequestResponse - [ ] RequestStream - [ ] RequestChannel diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index e4f7e6b..5d4a3c8 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -17,7 +17,7 @@ url = "2.1.1" tokio-tungstenite = "0.10.1" [dependencies.rsocket_rust] -path = "../rsocket" +version = "0.5.2" features = ["frame"] [dependencies.tokio] diff --git a/rsocket-transport-websocket/README.md b/rsocket-transport-websocket/README.md index ed040f4..cfea04e 100644 --- a/rsocket-transport-websocket/README.md +++ b/rsocket-transport-websocket/README.md @@ -6,9 +6,9 @@ Add dependencies in your `Cargo.toml`. ```toml [dependencies] -tokio = "0.2.16" -rsocket_rust = "0.5.1" -rsocket_rust_transport_websocket = "0.5.1" +tokio = "0.2.21" +rsocket_rust = "0.5.2" +rsocket_rust_transport_websocket = "0.5.2" ``` ### Server From da8bccc66f4add1137c663539ff8fd335b041cda Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Tue, 26 May 2020 22:50:49 +0800 Subject: [PATCH 14/70] upgrade version to v0.5.2. --- examples/Cargo.toml | 6 +++--- rsocket-benchmark/Cargo.toml | 8 ++++---- rsocket-test/Cargo.toml | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 1ba1217..51c9e5f 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -12,13 +12,13 @@ futures = "0.3.5" clap = "2.33.1" [dev-dependencies.rsocket_rust] -path = "../rsocket" +version = "0.5.2" [dev-dependencies.rsocket_rust_transport_tcp] -path = "../rsocket-transport-tcp" +version = "0.5.2" [dev-dependencies.rsocket_rust_transport_websocket] -path = "../rsocket-transport-websocket" +version = "0.5.2" [dev-dependencies.tokio] version = "0.2.21" diff --git a/rsocket-benchmark/Cargo.toml b/rsocket-benchmark/Cargo.toml index d204b1c..569cb40 100644 --- a/rsocket-benchmark/Cargo.toml +++ b/rsocket-benchmark/Cargo.toml @@ -17,17 +17,17 @@ serde_derive = "1.0.110" criterion = "0.3.2" [dev-dependencies.rsocket_rust] -path = "../rsocket" +version = "0.5.2" features = ["frame"] [dev-dependencies.rsocket_rust_transport_tcp] -path = "../rsocket-transport-tcp" +version = "0.5.2" [dev-dependencies.rsocket_rust_transport_websocket] -path = "../rsocket-transport-websocket" +version = "0.5.2" [dev-dependencies.rsocket_rust_messaging] -path = "../rsocket-messaging" +version = "0.5.2" [dev-dependencies.tokio] version = "0.2.21" diff --git a/rsocket-test/Cargo.toml b/rsocket-test/Cargo.toml index 9d05b99..8517a2f 100644 --- a/rsocket-test/Cargo.toml +++ b/rsocket-test/Cargo.toml @@ -16,19 +16,19 @@ serde = "1.0.110" serde_derive = "1.0.110" [dev-dependencies.rsocket_rust] -path = "../rsocket" +version = "0.5.2" features = ["frame"] [dev-dependencies.rsocket_rust_transport_tcp] -path = "../rsocket-transport-tcp" +version = "0.5.2" [dev-dependencies.rsocket_rust_transport_websocket] -path = "../rsocket-transport-websocket" +version = "0.5.2" [dev-dependencies.rsocket_rust_messaging] -path = "../rsocket-messaging" +version = "0.5.2" [dev-dependencies.tokio] -version = "0.2.20" +version = "0.2.21" default-features = false features = ["full"] From 4a4d2cd8b399c170f728e84f0d24dd3fe06ddde7 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Tue, 2 Jun 2020 23:14:50 +0800 Subject: [PATCH 15/70] add example for postgres. --- examples/Cargo.toml | 11 +++- examples/docker-compose.yml | 17 ++++++ examples/postgres.rs | 80 ++++++++++++++++++++++++++ justfile | 4 ++ rsocket-benchmark/Cargo.toml | 12 ++-- rsocket-messaging/Cargo.toml | 10 ++-- rsocket-test/Cargo.toml | 12 ++-- rsocket-transport-tcp/Cargo.toml | 4 +- rsocket-transport-wasm/Cargo.toml | 16 +++--- rsocket-transport-websocket/Cargo.toml | 4 +- rsocket/Cargo.toml | 2 +- 11 files changed, 140 insertions(+), 32 deletions(-) create mode 100644 examples/docker-compose.yml create mode 100644 examples/postgres.rs create mode 100644 justfile diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 51c9e5f..a5546e8 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -10,15 +10,18 @@ log = "0.4.8" env_logger = "0.7.1" futures = "0.3.5" clap = "2.33.1" +postgres = "0.17.3" +r2d2_postgres = "0.16.0" [dev-dependencies.rsocket_rust] -version = "0.5.2" +path = "../rsocket" [dev-dependencies.rsocket_rust_transport_tcp] -version = "0.5.2" +path = "../rsocket-transport-tcp" [dev-dependencies.rsocket_rust_transport_websocket] version = "0.5.2" +path = "../rsocket-transport-websocket" [dev-dependencies.tokio] version = "0.2.21" @@ -40,3 +43,7 @@ path = "cli.rs" [[example]] name = "qps" path = "qps.rs" + +[[example]] +name = "postgres" +path = "postgres.rs" diff --git a/examples/docker-compose.yml b/examples/docker-compose.yml new file mode 100644 index 0000000..e55419c --- /dev/null +++ b/examples/docker-compose.yml @@ -0,0 +1,17 @@ +version: '3.1' + +services: + postgres: + image: postgres:9.6-alpine + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + volumes: + - pgdata:/var/lib/postgresql/data + +volumes: + pgdata: + driver: local + diff --git a/examples/postgres.rs b/examples/postgres.rs new file mode 100644 index 0000000..fd68c7a --- /dev/null +++ b/examples/postgres.rs @@ -0,0 +1,80 @@ +#[macro_use] +extern crate log; + +use postgres::NoTls; +use r2d2_postgres::{ + r2d2::{self, Pool}, + PostgresConnectionManager, +}; +use rsocket_rust::{error::RSocketError, prelude::*}; +use rsocket_rust_transport_tcp::TcpServerTransport; +use std::error::Error; + +#[tokio::main] +async fn main() -> Result<(), Box> { + env_logger::builder().format_timestamp_millis().init(); + let dao = Dao::try_new().expect("Connect failed!"); + RSocketFactory::receive() + .acceptor(Box::new(move |_, _| { + info!("accept new socket!"); + Ok(Box::new(dao.clone())) + })) + .on_start(Box::new(|| info!("server start success!!!"))) + .transport(TcpServerTransport::from("127.0.0.1:7878")) + .serve() + .await +} + +#[derive(Clone, Debug)] +struct Dao { + pool: Pool>, +} + +impl RSocket for Dao { + fn request_response(&self, _: Payload) -> Mono> { + let pool = self.pool.clone(); + Box::pin(async move { + // TODO: something wrong here!!! + let mut client = pool.get().expect("Get client from pool failed!"); + let row = client + .query_one("SELECT 'world' AS hello", &[]) + .expect("Execute SQL failed!"); + let result: String = row.get("hello"); + Ok(Payload::builder().set_data_utf8(&result).build()) + }) + } + + fn metadata_push(&self, _: Payload) -> Mono<()> { + unimplemented!() + } + + fn fire_and_forget(&self, _: Payload) -> Mono<()> { + unimplemented!() + } + + fn request_stream(&self, _: Payload) -> Flux> { + unimplemented!() + } + + fn request_channel( + &self, + _: Flux>, + ) -> Flux> { + unimplemented!() + } +} + +impl Dao { + fn try_new() -> Result> { + let manager: PostgresConnectionManager = PostgresConnectionManager::new( + "host=localhost user=postgres password=postgres" + .parse() + .unwrap(), + NoTls, + ); + let pool: Pool> = + r2d2::Pool::new(manager).expect("Create pool failed!"); + info!("==> create postgres pool success!"); + Ok(Dao { pool }) + } +} diff --git a/justfile b/justfile new file mode 100644 index 0000000..3193f9f --- /dev/null +++ b/justfile @@ -0,0 +1,4 @@ +default: + echo 'Hello, world!' +test: + @cargo test -- --nocapture diff --git a/rsocket-benchmark/Cargo.toml b/rsocket-benchmark/Cargo.toml index 569cb40..fc1af87 100644 --- a/rsocket-benchmark/Cargo.toml +++ b/rsocket-benchmark/Cargo.toml @@ -12,22 +12,22 @@ env_logger = "0.7.1" bytes = "0.5.4" hex = "0.4.2" rand = "0.7.3" -serde = "1.0.110" -serde_derive = "1.0.110" +serde = "1.0.111" +serde_derive = "1.0.111" criterion = "0.3.2" [dev-dependencies.rsocket_rust] -version = "0.5.2" +path = "../rsocket" features = ["frame"] [dev-dependencies.rsocket_rust_transport_tcp] -version = "0.5.2" +path = "../rsocket-transport-tcp" [dev-dependencies.rsocket_rust_transport_websocket] -version = "0.5.2" +path = "../rsocket-transport-websocket" [dev-dependencies.rsocket_rust_messaging] -version = "0.5.2" +path = "../rsocket-messaging" [dev-dependencies.tokio] version = "0.2.21" diff --git a/rsocket-messaging/Cargo.toml b/rsocket-messaging/Cargo.toml index ada8909..15cd618 100644 --- a/rsocket-messaging/Cargo.toml +++ b/rsocket-messaging/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_messaging" -version = "0.5.2" +version = "0.5.3" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" @@ -12,18 +12,18 @@ description = "Communicate with Spring RSocket Messaging." [dependencies] futures = "0.3.5" bytes = "0.5.4" -serde = "1.0.110" +serde = "1.0.111" serde_json = "1.0.53" serde_cbor = "0.11.1" hex = "0.4.2" url = "2.1.1" [dependencies.rsocket_rust] -version = "0.5.2" +path = "../rsocket" features = ["frame"] [dependencies.rsocket_rust_transport_tcp] -version = "0.5.2" +path = "../rsocket-transport-tcp" [dependencies.rsocket_rust_transport_websocket] -version = "0.5.2" +path = "../rsocket-transport-websocket" diff --git a/rsocket-test/Cargo.toml b/rsocket-test/Cargo.toml index 8517a2f..4df44fc 100644 --- a/rsocket-test/Cargo.toml +++ b/rsocket-test/Cargo.toml @@ -12,21 +12,21 @@ env_logger = "0.7.1" bytes = "0.5.4" hex = "0.4.2" rand = "0.7.3" -serde = "1.0.110" -serde_derive = "1.0.110" +serde = "1.0.111" +serde_derive = "1.0.111" [dev-dependencies.rsocket_rust] -version = "0.5.2" +path = "../rsocket" features = ["frame"] [dev-dependencies.rsocket_rust_transport_tcp] -version = "0.5.2" +path = "../rsocket-transport-tcp" [dev-dependencies.rsocket_rust_transport_websocket] -version = "0.5.2" +path = "../rsocket-transport-websocket" [dev-dependencies.rsocket_rust_messaging] -version = "0.5.2" +path = "../rsocket-messaging" [dev-dependencies.tokio] version = "0.2.21" diff --git a/rsocket-transport-tcp/Cargo.toml b/rsocket-transport-tcp/Cargo.toml index bbc7e0c..ed59a7a 100644 --- a/rsocket-transport-tcp/Cargo.toml +++ b/rsocket-transport-tcp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_tcp" -version = "0.5.2" +version = "0.5.3" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" @@ -15,7 +15,7 @@ futures = "0.3.5" bytes = "0.5.4" [dependencies.rsocket_rust] -version = "0.5.2" +path = "../rsocket" features = ["frame"] [dependencies.tokio] diff --git a/rsocket-transport-wasm/Cargo.toml b/rsocket-transport-wasm/Cargo.toml index ffc2844..ec0aa2b 100644 --- a/rsocket-transport-wasm/Cargo.toml +++ b/rsocket-transport-wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_wasm" -version = "0.5.2" +version = "0.5.3" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" @@ -11,23 +11,23 @@ description = "WASM Websocket RSocket transport implementation." [dependencies] bytes = "0.5.4" -wasm-bindgen-futures = "0.4.12" +wasm-bindgen-futures = "0.4.13" futures-channel = "0.3.5" futures-util = "0.3.5" -js-sys = "0.3.39" -serde = "1.0.110" -serde_derive = "1.0.110" +js-sys = "0.3.40" +serde = "1.0.111" +serde_derive = "1.0.111" [dependencies.rsocket_rust] -version = "0.5.2" +path = "../rsocket" features = ["frame"] [dependencies.wasm-bindgen] -version = "0.2.62" +version = "0.2.63" features = ["serde-serialize"] [dependencies.web-sys] -version = "0.3.39" +version = "0.3.40" features = [ "FileReader", "ProgressEvent", diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index 5d4a3c8..737f085 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_websocket" -version = "0.5.2" +version = "0.5.3" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" @@ -17,7 +17,7 @@ url = "2.1.1" tokio-tungstenite = "0.10.1" [dependencies.rsocket_rust] -version = "0.5.2" +path = "../rsocket" features = ["frame"] [dependencies.tokio] diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index 07738a5..50479d4 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust" -version = "0.5.2" +version = "0.5.3" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" From 49c74b241cc6746e9387b76fb374d29866236c33 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Thu, 4 Jun 2020 23:32:39 +0800 Subject: [PATCH 16/70] remove Sync trait for Mono and Flux. --- examples/Cargo.toml | 3 +-- examples/postgres.rs | 49 ++++++++++++++++++++++---------------------- rsocket/src/spi.rs | 4 ++-- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index a5546e8..bce4f52 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -10,8 +10,7 @@ log = "0.4.8" env_logger = "0.7.1" futures = "0.3.5" clap = "2.33.1" -postgres = "0.17.3" -r2d2_postgres = "0.16.0" +tokio-postgres = "0.5.4" [dev-dependencies.rsocket_rust] path = "../rsocket" diff --git a/examples/postgres.rs b/examples/postgres.rs index fd68c7a..f940bb5 100644 --- a/examples/postgres.rs +++ b/examples/postgres.rs @@ -1,43 +1,36 @@ #[macro_use] extern crate log; -use postgres::NoTls; -use r2d2_postgres::{ - r2d2::{self, Pool}, - PostgresConnectionManager, -}; use rsocket_rust::{error::RSocketError, prelude::*}; use rsocket_rust_transport_tcp::TcpServerTransport; use std::error::Error; +use std::sync::Arc; +use tokio_postgres::{Client as PgClient, NoTls}; #[tokio::main] async fn main() -> Result<(), Box> { env_logger::builder().format_timestamp_millis().init(); - let dao = Dao::try_new().expect("Connect failed!"); + let dao = Dao::try_new().await?; RSocketFactory::receive() - .acceptor(Box::new(move |_, _| { - info!("accept new socket!"); - Ok(Box::new(dao.clone())) - })) + .acceptor(Box::new(move |_, _| Ok(Box::new(dao.clone())))) .on_start(Box::new(|| info!("server start success!!!"))) .transport(TcpServerTransport::from("127.0.0.1:7878")) .serve() .await } -#[derive(Clone, Debug)] +#[derive(Clone)] struct Dao { - pool: Pool>, + client: Arc, } impl RSocket for Dao { fn request_response(&self, _: Payload) -> Mono> { - let pool = self.pool.clone(); + let client = self.client.clone(); Box::pin(async move { - // TODO: something wrong here!!! - let mut client = pool.get().expect("Get client from pool failed!"); let row = client .query_one("SELECT 'world' AS hello", &[]) + .await .expect("Execute SQL failed!"); let result: String = row.get("hello"); Ok(Payload::builder().set_data_utf8(&result).build()) @@ -65,16 +58,22 @@ impl RSocket for Dao { } impl Dao { - fn try_new() -> Result> { - let manager: PostgresConnectionManager = PostgresConnectionManager::new( - "host=localhost user=postgres password=postgres" - .parse() - .unwrap(), - NoTls, - ); - let pool: Pool> = - r2d2::Pool::new(manager).expect("Create pool failed!"); + async fn try_new() -> Result> { + let (client, connection) = + tokio_postgres::connect("host=localhost user=postgres password=postgres", NoTls) + .await?; + + // The connection object performs the actual communication with the database, + // so spawn it off to run on its own. + tokio::spawn(async move { + if let Err(e) = connection.await { + eprintln!("connection error: {}", e); + } + }); + info!("==> create postgres pool success!"); - Ok(Dao { pool }) + Ok(Dao { + client: Arc::new(client), + }) } } diff --git a/rsocket/src/spi.rs b/rsocket/src/spi.rs index 39f4451..37fa213 100644 --- a/rsocket/src/spi.rs +++ b/rsocket/src/spi.rs @@ -18,8 +18,8 @@ pub type ServerResponder = Box< + Fn(SetupPayload, Box) -> Result, Box>, >; -pub type Mono = Pin>>; -pub type Flux = Pin>>; +pub type Mono = Pin>>; +pub type Flux = Pin>>; pub trait RSocket: Sync + Send { fn metadata_push(&self, req: Payload) -> Mono<()>; From 80e2d166955161a60562b69b92312435486a2830 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Fri, 5 Jun 2020 23:40:18 +0800 Subject: [PATCH 17/70] add redis example. --- examples/Cargo.toml | 5 +++ examples/docker-compose.yml | 6 +++- examples/redis.rs | 64 +++++++++++++++++++++++++++++++++++++ rsocket/Cargo.toml | 1 + 4 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 examples/redis.rs diff --git a/examples/Cargo.toml b/examples/Cargo.toml index bce4f52..d055dd3 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -11,6 +11,7 @@ env_logger = "0.7.1" futures = "0.3.5" clap = "2.33.1" tokio-postgres = "0.5.4" +redis = "0.16.0" [dev-dependencies.rsocket_rust] path = "../rsocket" @@ -46,3 +47,7 @@ path = "qps.rs" [[example]] name = "postgres" path = "postgres.rs" + +[[example]] +name = "redis" +path = "redis.rs" diff --git a/examples/docker-compose.yml b/examples/docker-compose.yml index e55419c..10c6812 100644 --- a/examples/docker-compose.yml +++ b/examples/docker-compose.yml @@ -10,8 +10,12 @@ services: - 5432:5432 volumes: - pgdata:/var/lib/postgresql/data + redis: + image: "redis:3-alpine" + ports: + - "6379:6379" + command: ["redis-server", "--appendonly", "yes"] volumes: pgdata: driver: local - diff --git a/examples/redis.rs b/examples/redis.rs new file mode 100644 index 0000000..e19d9d8 --- /dev/null +++ b/examples/redis.rs @@ -0,0 +1,64 @@ +use redis::Client as RedisClient; +use rsocket_rust::{error::RSocketError, prelude::*}; +use rsocket_rust_transport_tcp::TcpServerTransport; +use std::error::Error; +use std::str::FromStr; + +#[derive(Clone)] +struct RedisDao { + inner: RedisClient, +} + +#[tokio::main] +async fn main() -> Result<(), Box> { + let dao = RedisDao::from_str("redis://127.0.0.1").expect("Connect redis failed!"); + RSocketFactory::receive() + .acceptor(Box::new(move |_setup, _socket| Ok(Box::new(dao.clone())))) + .transport(TcpServerTransport::from("127.0.0.1:7878")) + .serve() + .await +} + +impl FromStr for RedisDao { + type Err = redis::RedisError; + + fn from_str(s: &str) -> Result { + let client = redis::Client::open(s)?; + Ok(RedisDao { inner: client }) + } +} + +impl RSocket for RedisDao { + fn request_response(&self, req: Payload) -> Mono> { + let client = self.inner.clone(); + + Box::pin(async move { + let mut conn: redis::aio::Connection = client + .get_async_connection() + .await + .expect("Connect redis failed!"); + let value: String = redis::cmd("GET") + .arg(&[req.data_utf8()]) + .query_async(&mut conn) + .await + .unwrap_or("".to_owned()); + Ok(Payload::builder().set_data_utf8(&value).build()) + }) + } + + fn metadata_push(&self, _req: Payload) -> Mono<()> { + unimplemented!() + } + fn fire_and_forget(&self, _req: Payload) -> Mono<()> { + unimplemented!() + } + fn request_stream(&self, _req: Payload) -> Flux> { + unimplemented!() + } + fn request_channel( + &self, + _reqs: Flux>, + ) -> Flux> { + unimplemented!() + } +} diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index 50479d4..a174ad4 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -14,6 +14,7 @@ log = "0.4.8" bytes = "0.5.4" futures = "0.3.5" lazy_static = "1.4.0" +async-trait = "0.1.33" [dependencies.tokio] version = "0.2.21" From d609c6dacdac70635bfa207d32c2d0d91597358d Mon Sep 17 00:00:00 2001 From: seal90 <578935869@qq.com> Date: Thu, 11 Jun 2020 20:57:32 +0800 Subject: [PATCH 18/70] support for unix domain socket --- .gitignore | 2 +- Cargo.toml | 1 + examples/Cargo.toml | 11 +++ examples/echo-uds-client.rs | 32 ++++++++ examples/echo-uds.rs | 29 +++++++ rsocket-test/Cargo.toml | 3 + rsocket-test/tests/test_clients.rs | 47 +++++++++++ rsocket-transport-unix/Cargo.toml | 29 +++++++ rsocket-transport-unix/README.md | 85 ++++++++++++++++++++ rsocket-transport-unix/src/client.rs | 114 +++++++++++++++++++++++++++ rsocket-transport-unix/src/codec.rs | 40 ++++++++++ rsocket-transport-unix/src/lib.rs | 11 +++ rsocket-transport-unix/src/server.rs | 70 ++++++++++++++++ 13 files changed, 473 insertions(+), 1 deletion(-) create mode 100644 examples/echo-uds-client.rs create mode 100644 examples/echo-uds.rs create mode 100644 rsocket-transport-unix/Cargo.toml create mode 100644 rsocket-transport-unix/README.md create mode 100644 rsocket-transport-unix/src/client.rs create mode 100644 rsocket-transport-unix/src/codec.rs create mode 100644 rsocket-transport-unix/src/lib.rs create mode 100644 rsocket-transport-unix/src/server.rs diff --git a/.gitignore b/.gitignore index 62518ff..8aba189 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ target/ **/*.rs.bk Cargo.lock - +.vscode/ diff --git a/Cargo.toml b/Cargo.toml index 5c0bb67..2c68ae7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ members = [ "rsocket", # transports "rsocket-transport-tcp", +"rsocket-transport-unix", "rsocket-transport-websocket", "rsocket-transport-wasm", # extra diff --git a/examples/Cargo.toml b/examples/Cargo.toml index d055dd3..31ec241 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -19,6 +19,9 @@ path = "../rsocket" [dev-dependencies.rsocket_rust_transport_tcp] path = "../rsocket-transport-tcp" +[dev-dependencies.rsocket_rust_transport_unix] +path = "../rsocket-transport-unix" + [dev-dependencies.rsocket_rust_transport_websocket] version = "0.5.2" path = "../rsocket-transport-websocket" @@ -51,3 +54,11 @@ path = "postgres.rs" [[example]] name = "redis" path = "redis.rs" + +[[example]] +name = "echo-uds" +path = "echo-uds.rs" + +[[example]] +name = "echo-uds-client" +path = "echo-uds-client.rs" \ No newline at end of file diff --git a/examples/echo-uds-client.rs b/examples/echo-uds-client.rs new file mode 100644 index 0000000..8c99c24 --- /dev/null +++ b/examples/echo-uds-client.rs @@ -0,0 +1,32 @@ +use log::info; +use rsocket_rust::prelude::{ClientResponder, EchoRSocket, Payload, RSocket, RSocketFactory}; +use rsocket_rust_transport_unix::UnixClientTransport; +use std::error::Error; + +#[tokio::main] +async fn main() -> Result<(), Box> { + + let responder: ClientResponder = Box::new(|| Box::new(EchoRSocket)); + + let client = RSocketFactory::connect() + .acceptor(responder) + .transport(UnixClientTransport::from("/tmp/rsocket-uds.sock")) + .setup(Payload::from("READY!")) + .mime_type("text/plain", "text/plain") + .start() + .await + .unwrap(); + + let request_payload: Payload = Payload::builder() + .set_data_utf8("Hello World!") + .set_metadata_utf8("Rust") + .build(); + + let res = client.request_response(request_payload).await.unwrap(); + + info!("got: {:?}", res); + + client.close(); + + Ok(()) +} \ No newline at end of file diff --git a/examples/echo-uds.rs b/examples/echo-uds.rs new file mode 100644 index 0000000..be40fdf --- /dev/null +++ b/examples/echo-uds.rs @@ -0,0 +1,29 @@ +use log::info; +use rsocket_rust::prelude::{EchoRSocket, RSocketFactory, ServerResponder}; +use rsocket_rust_transport_unix::UnixServerTransport; +use std::error::Error; + +#[tokio::main] +async fn main() -> Result<(), Box> { + + let transport: UnixServerTransport = UnixServerTransport::from("/tmp/rsocket-uds.sock"); + + let responder: ServerResponder = Box::new(|setup, _socket| { + info!("accept setup: {:?}", setup); + Ok(Box::new(EchoRSocket)) + // Or you can reject setup + // Err(From::from("SETUP_NOT_ALLOW")) + }); + + let on_start: Box = + Box::new(|| info!("+++++++ echo server started! +++++++")); + + RSocketFactory::receive() + .transport(transport) + .acceptor(responder) + .on_start(on_start) + .serve() + .await?; + + Ok(()) +} \ No newline at end of file diff --git a/rsocket-test/Cargo.toml b/rsocket-test/Cargo.toml index 4df44fc..50e0fab 100644 --- a/rsocket-test/Cargo.toml +++ b/rsocket-test/Cargo.toml @@ -22,6 +22,9 @@ features = ["frame"] [dev-dependencies.rsocket_rust_transport_tcp] path = "../rsocket-transport-tcp" +[dev-dependencies.rsocket_rust_transport_unix] +path = "../rsocket-transport-unix" + [dev-dependencies.rsocket_rust_transport_websocket] path = "../rsocket-transport-websocket" diff --git a/rsocket-test/tests/test_clients.rs b/rsocket-test/tests/test_clients.rs index e024e48..e8062cb 100644 --- a/rsocket-test/tests/test_clients.rs +++ b/rsocket-test/tests/test_clients.rs @@ -4,6 +4,7 @@ extern crate log; use futures::stream; use rsocket_rust::prelude::*; use rsocket_rust_transport_tcp::{TcpClientTransport, TcpServerTransport}; +use rsocket_rust_transport_unix::{UnixClientTransport, UnixServerTransport}; use rsocket_rust_transport_websocket::{WebsocketClientTransport, WebsocketServerTransport}; use std::thread::sleep; use std::time::Duration; @@ -120,6 +121,52 @@ fn test_tcp() { }); } +#[test] +fn test_unix() { + init(); + + let addr = "/tmp/rsocket-uds.sock"; + + let server_runtime = Runtime::new().unwrap(); + + // spawn a server + server_runtime.spawn(async move { + RSocketFactory::receive() + .transport(UnixServerTransport::from(addr)) + .acceptor(Box::new(|setup, _socket| { + info!("accept setup: {:?}", setup); + Ok(Box::new(EchoRSocket)) + })) + .on_start(Box::new(|| { + info!("+++++++ unix echo server started! +++++++") + })) + .serve() + .await + }); + + sleep(Duration::from_millis(500)); + + let mut client_runtime = Runtime::new().unwrap(); + + client_runtime.block_on(async { + let cli = RSocketFactory::connect() + .acceptor(Box::new(|| Box::new(EchoRSocket))) + .transport(UnixClientTransport::from(addr)) + .setup(Payload::from("READY!")) + .mime_type("text/plain", "text/plain") + .start() + .await + .unwrap(); + + exec_metadata_push(&cli).await; + exec_fire_and_forget(&cli).await; + exec_request_response(&cli).await; + exec_request_stream(&cli).await; + exec_request_channel(&cli).await; + cli.close(); + }); +} + #[tokio::main] #[test] #[ignore] diff --git a/rsocket-transport-unix/Cargo.toml b/rsocket-transport-unix/Cargo.toml new file mode 100644 index 0000000..bdb8f85 --- /dev/null +++ b/rsocket-transport-unix/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "rsocket_rust_transport_unix" +version = "0.5.3" +authors = ["seal <578935869@qq.com>"] +edition = "2018" +license = "Apache-2.0" +readme = "README.md" +repository = "https://github.com/rsocket/rsocket-rust" +homepage = "https://github.com/rsocket/rsocket-rust" +description = "Unix Domain Socket RSocket transport implementation." + +[dependencies] +log = "0.4.8" +futures = "0.3.5" +bytes = "0.5.4" + +[dependencies.rsocket_rust] +path = "../rsocket" +features = ["frame"] + +[dependencies.tokio] +version = "0.2.21" +default-features = false +features = [ "rt-core", "rt-threaded", "uds", "sync", "stream" ] + +[dependencies.tokio-util] +version = "0.3.1" +default-features = false +features = ["codec"] \ No newline at end of file diff --git a/rsocket-transport-unix/README.md b/rsocket-transport-unix/README.md new file mode 100644 index 0000000..a9d281d --- /dev/null +++ b/rsocket-transport-unix/README.md @@ -0,0 +1,85 @@ +# RSocket Transport For Unix Domain Socket + +## Example + +Add dependencies in your `Cargo.toml`. + +```toml +[dependencies] +tokio = "0.2.21" +rsocket_rust = "0.5.3" +rsocket_rust_transport_unix = "0.5.3" +``` + +### Server + +```rust +use log::info; +use rsocket_rust::prelude::{EchoRSocket, RSocketFactory, ServerResponder}; +use rsocket_rust_transport_unix::UnixServerTransport; +use std::error::Error; + +#[tokio::main] +async fn main() -> Result<(), Box> { + + let transport: UnixServerTransport = UnixServerTransport::from("/tmp/rsocket-uds.sock"); + + let responder: ServerResponder = Box::new(|setup, _socket| { + info!("accept setup: {:?}", setup); + Ok(Box::new(EchoRSocket)) + // Or you can reject setup + // Err(From::from("SETUP_NOT_ALLOW")) + }); + + let on_start: Box = + Box::new(|| info!("+++++++ echo server started! +++++++")); + + RSocketFactory::receive() + .transport(transport) + .acceptor(responder) + .on_start(on_start) + .serve() + .await?; + + Ok(()) +} + +``` + +### Client + +```rust +use log::info; +use rsocket_rust::prelude::{ClientResponder, EchoRSocket, Payload, RSocket, RSocketFactory}; +use rsocket_rust_transport_unix::UnixClientTransport; +use std::error::Error; + +#[tokio::main] +async fn main() -> Result<(), Box> { + + let responder: ClientResponder = Box::new(|| Box::new(EchoRSocket)); + + let client = RSocketFactory::connect() + .acceptor(responder) + .transport(UnixClientTransport::from("/tmp/rsocket-uds.sock")) + .setup(Payload::from("READY!")) + .mime_type("text/plain", "text/plain") + .start() + .await + .unwrap(); + + let request_payload: Payload = Payload::builder() + .set_data_utf8("Hello World!") + .set_metadata_utf8("Rust") + .build(); + + let res = client.request_response(request_payload).await.unwrap(); + + info!("got: {:?}", res); + + client.close(); + + Ok(()) +} + +``` diff --git a/rsocket-transport-unix/src/client.rs b/rsocket-transport-unix/src/client.rs new file mode 100644 index 0000000..1e90835 --- /dev/null +++ b/rsocket-transport-unix/src/client.rs @@ -0,0 +1,114 @@ +use super::codec::LengthBasedFrameCodec; +use futures::{SinkExt, StreamExt}; +use std::os::unix::net::UnixStream as StdUnixStream; +use std::str::FromStr; +use std::io; +use tokio::net::UnixStream; +use tokio_util::codec::Framed; +use rsocket_rust::error::RSocketError; +use rsocket_rust::frame::Frame; +use rsocket_rust::runtime::{DefaultSpawner, Spawner}; +use rsocket_rust::transport::{ClientTransport, Rx, Tx, TxOnce}; + +enum Connector { + Direct(UnixStream), + Lazy(String), +} + +pub struct UnixClientTransport { + connector: Connector, +} + +impl UnixClientTransport { + + #[inline] + fn new(connector: Connector) -> UnixClientTransport { + UnixClientTransport{ connector } + } + + #[inline] + async fn connect(self) -> Result { + match self.connector { + Connector::Direct(stream) => Ok(stream), + Connector::Lazy(addr) => match StdUnixStream::connect(&addr) { + Ok(raw) => match UnixStream::from_std(raw) { + Ok(stream) => Ok(stream), + Err(e) => Err(RSocketError::from(e)), + }, + Err(e) => Err(RSocketError::from(e)), + }, + } + } +} + +impl ClientTransport for UnixClientTransport { + fn attach( + self, + incoming: Tx, + mut sending: Rx, + connected: Option>>, + ) { + DefaultSpawner.spawn(async move { + match self.connect().await { + Ok(socket) => { + if let Some(sender) = connected { + sender.send(Ok(())).unwrap(); + } + let (mut writer, mut reader) = + Framed::new(socket, LengthBasedFrameCodec).split(); + DefaultSpawner.spawn(async move { + while let Some(it) = reader.next().await { + incoming.unbounded_send(it.unwrap()).unwrap(); + } + }); + // loop write + while let Some(it) = sending.next().await { + debug!("===> SND: {:?}", &it); + writer.send(it).await.unwrap() + } + } + Err(e) => { + if let Some(sender) = connected { + sender.send(Err(e)).unwrap(); + } + } + } + }); + } +} + +impl FromStr for UnixClientTransport { + type Err = io::Error; + + fn from_str(addr: &str) -> Result { + let socket_addr = if addr.starts_with("unix://") || addr.starts_with("UNIX://") { + addr.chars().skip(7).collect::() + } else { + addr.to_string() + }; + Ok(UnixClientTransport::new(Connector::Lazy(socket_addr))) + } +} + +impl From for UnixClientTransport { + fn from(addr: String) -> UnixClientTransport { + UnixClientTransport::new(Connector::Lazy(addr)) + } +} + +impl From<&str> for UnixClientTransport { + fn from(addr: &str) -> UnixClientTransport { + let socket_addr: String = if addr.starts_with("tcp://") || addr.starts_with("TCP://") { + addr.chars().skip(6).collect::() + } else { + addr.to_string() + }; + UnixClientTransport::new(Connector::Lazy(socket_addr)) + } +} + +impl From for UnixClientTransport { + fn from(socket: UnixStream) -> UnixClientTransport { + UnixClientTransport::new(Connector::Direct(socket)) + } +} diff --git a/rsocket-transport-unix/src/codec.rs b/rsocket-transport-unix/src/codec.rs new file mode 100644 index 0000000..606a629 --- /dev/null +++ b/rsocket-transport-unix/src/codec.rs @@ -0,0 +1,40 @@ +use bytes::{Buf, BytesMut}; +use rsocket_rust::frame::Frame; +use rsocket_rust::utils::{u24, Writeable}; +use std::io::{Error, ErrorKind}; +use tokio_util::codec::{Decoder, Encoder}; + +pub struct LengthBasedFrameCodec; + +impl Decoder for LengthBasedFrameCodec { + type Item = Frame; + type Error = Error; + + fn decode(&mut self, buf: &mut BytesMut) -> Result, Self::Error> { + let actual = buf.len(); + if actual < 3 { + return Ok(None); + } + let l = u24::read(buf).into(); + if actual < 3 + l { + return Ok(None); + } + buf.advance(3); + let mut bb = buf.split_to(l); + match Frame::decode(&mut bb) { + Ok(v) => Ok(Some(v)), + Err(_e) => Err(Error::from(ErrorKind::InvalidInput)), + } + } +} + +impl Encoder for LengthBasedFrameCodec { + type Error = Error; + fn encode(&mut self, item: Frame, buf: &mut BytesMut) -> Result<(), Self::Error> { + let l = item.len(); + buf.reserve(3 + l); + u24::from(l).write_to(buf); + item.write_to(buf); + Ok(()) + } +} diff --git a/rsocket-transport-unix/src/lib.rs b/rsocket-transport-unix/src/lib.rs new file mode 100644 index 0000000..1b92519 --- /dev/null +++ b/rsocket-transport-unix/src/lib.rs @@ -0,0 +1,11 @@ +#![allow(clippy::type_complexity)] + +#[macro_use] +extern crate log; + +mod client; +mod server; +mod codec; + +pub use client::UnixClientTransport; +pub use server::UnixServerTransport; \ No newline at end of file diff --git a/rsocket-transport-unix/src/server.rs b/rsocket-transport-unix/src/server.rs new file mode 100644 index 0000000..234330a --- /dev/null +++ b/rsocket-transport-unix/src/server.rs @@ -0,0 +1,70 @@ +use super::client::UnixClientTransport; +use rsocket_rust::transport::{ClientTransport, ServerTransport}; +use std::error::Error; +use std::future::Future; +use std::pin::Pin; +use tokio::net::UnixListener; + +pub struct UnixServerTransport { + addr: String, +} + +impl UnixServerTransport { + fn new(addr: String) -> UnixServerTransport { + UnixServerTransport { addr } + } +} + +impl ServerTransport for UnixServerTransport { + type Item = UnixClientTransport; + + fn start( + self, + starter: Option>, + acceptor: impl Fn(Self::Item) + Send + Sync + 'static, + ) -> Pin>>>> + where + Self::Item: ClientTransport + Sized, + { + Box::pin(async move { + match UnixListener::bind(&self.addr.as_str()){ + Ok(mut listener) => { + debug!("listening on: {}", &self.addr); + if let Some(mut bingo) = starter { + bingo(); + } + while let Ok((socket, _)) = listener.accept().await { + let tp = UnixClientTransport::from(socket); + acceptor(tp); + } + + Ok(()) + } + Err(e) => Err(e.into_inner().unwrap()), + } + }) + } +} + +impl Drop for UnixServerTransport { + fn drop(&mut self) { + std::fs::remove_file(&self.addr.as_str()).unwrap(); + } +} +// impl From for UnixServerTransport { +// fn from(addr: SocketAddr) -> UnixServerTransport { +// UnixServerTransport::new(addr) +// } +// } + +impl From for UnixServerTransport { + fn from(addr: String) -> UnixServerTransport { + UnixServerTransport::new(addr.parse().unwrap()) + } +} + +impl From<&str> for UnixServerTransport { + fn from(addr: &str) -> UnixServerTransport { + UnixServerTransport::new(addr.parse().unwrap()) + } +} From 619049211ca638d22f9109c84dc59f2e380dcab3 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Thu, 11 Jun 2020 22:29:52 +0800 Subject: [PATCH 19/70] Reformat codes. --- examples/echo-uds-client.rs | 3 +-- examples/echo-uds.rs | 3 +-- rsocket-transport-unix/src/client.rs | 13 ++++++------- rsocket-transport-unix/src/lib.rs | 4 ++-- rsocket-transport-unix/src/server.rs | 4 ++-- 5 files changed, 12 insertions(+), 15 deletions(-) diff --git a/examples/echo-uds-client.rs b/examples/echo-uds-client.rs index 8c99c24..e075de4 100644 --- a/examples/echo-uds-client.rs +++ b/examples/echo-uds-client.rs @@ -5,7 +5,6 @@ use std::error::Error; #[tokio::main] async fn main() -> Result<(), Box> { - let responder: ClientResponder = Box::new(|| Box::new(EchoRSocket)); let client = RSocketFactory::connect() @@ -29,4 +28,4 @@ async fn main() -> Result<(), Box> { client.close(); Ok(()) -} \ No newline at end of file +} diff --git a/examples/echo-uds.rs b/examples/echo-uds.rs index be40fdf..ecd6477 100644 --- a/examples/echo-uds.rs +++ b/examples/echo-uds.rs @@ -5,7 +5,6 @@ use std::error::Error; #[tokio::main] async fn main() -> Result<(), Box> { - let transport: UnixServerTransport = UnixServerTransport::from("/tmp/rsocket-uds.sock"); let responder: ServerResponder = Box::new(|setup, _socket| { @@ -26,4 +25,4 @@ async fn main() -> Result<(), Box> { .await?; Ok(()) -} \ No newline at end of file +} diff --git a/rsocket-transport-unix/src/client.rs b/rsocket-transport-unix/src/client.rs index 1e90835..eac4b57 100644 --- a/rsocket-transport-unix/src/client.rs +++ b/rsocket-transport-unix/src/client.rs @@ -1,14 +1,14 @@ use super::codec::LengthBasedFrameCodec; use futures::{SinkExt, StreamExt}; -use std::os::unix::net::UnixStream as StdUnixStream; -use std::str::FromStr; -use std::io; -use tokio::net::UnixStream; -use tokio_util::codec::Framed; use rsocket_rust::error::RSocketError; use rsocket_rust::frame::Frame; use rsocket_rust::runtime::{DefaultSpawner, Spawner}; use rsocket_rust::transport::{ClientTransport, Rx, Tx, TxOnce}; +use std::io; +use std::os::unix::net::UnixStream as StdUnixStream; +use std::str::FromStr; +use tokio::net::UnixStream; +use tokio_util::codec::Framed; enum Connector { Direct(UnixStream), @@ -20,10 +20,9 @@ pub struct UnixClientTransport { } impl UnixClientTransport { - #[inline] fn new(connector: Connector) -> UnixClientTransport { - UnixClientTransport{ connector } + UnixClientTransport { connector } } #[inline] diff --git a/rsocket-transport-unix/src/lib.rs b/rsocket-transport-unix/src/lib.rs index 1b92519..7ec5d51 100644 --- a/rsocket-transport-unix/src/lib.rs +++ b/rsocket-transport-unix/src/lib.rs @@ -4,8 +4,8 @@ extern crate log; mod client; -mod server; mod codec; +mod server; pub use client::UnixClientTransport; -pub use server::UnixServerTransport; \ No newline at end of file +pub use server::UnixServerTransport; diff --git a/rsocket-transport-unix/src/server.rs b/rsocket-transport-unix/src/server.rs index 234330a..b5aa145 100644 --- a/rsocket-transport-unix/src/server.rs +++ b/rsocket-transport-unix/src/server.rs @@ -27,7 +27,7 @@ impl ServerTransport for UnixServerTransport { Self::Item: ClientTransport + Sized, { Box::pin(async move { - match UnixListener::bind(&self.addr.as_str()){ + match UnixListener::bind(&self.addr.as_str()) { Ok(mut listener) => { debug!("listening on: {}", &self.addr); if let Some(mut bingo) = starter { @@ -37,7 +37,7 @@ impl ServerTransport for UnixServerTransport { let tp = UnixClientTransport::from(socket); acceptor(tp); } - + Ok(()) } Err(e) => Err(e.into_inner().unwrap()), From f2a05bc95cb7045c9e44af9d39f669bfe54f9d59 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Thu, 11 Jun 2020 22:34:06 +0800 Subject: [PATCH 20/70] Fix unix schema bug. --- rsocket-transport-unix/src/client.rs | 4 ++-- rsocket-transport-unix/src/server.rs | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/rsocket-transport-unix/src/client.rs b/rsocket-transport-unix/src/client.rs index eac4b57..087345a 100644 --- a/rsocket-transport-unix/src/client.rs +++ b/rsocket-transport-unix/src/client.rs @@ -97,8 +97,8 @@ impl From for UnixClientTransport { impl From<&str> for UnixClientTransport { fn from(addr: &str) -> UnixClientTransport { - let socket_addr: String = if addr.starts_with("tcp://") || addr.starts_with("TCP://") { - addr.chars().skip(6).collect::() + let socket_addr: String = if addr.starts_with("unix://") || addr.starts_with("UNIX://") { + addr.chars().skip(7).collect::() } else { addr.to_string() }; diff --git a/rsocket-transport-unix/src/server.rs b/rsocket-transport-unix/src/server.rs index b5aa145..45695b2 100644 --- a/rsocket-transport-unix/src/server.rs +++ b/rsocket-transport-unix/src/server.rs @@ -51,11 +51,6 @@ impl Drop for UnixServerTransport { std::fs::remove_file(&self.addr.as_str()).unwrap(); } } -// impl From for UnixServerTransport { -// fn from(addr: SocketAddr) -> UnixServerTransport { -// UnixServerTransport::new(addr) -// } -// } impl From for UnixServerTransport { fn from(addr: String) -> UnixServerTransport { From 9cf3f70ea44932e378c10e7f5f575716c48dedc5 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Thu, 11 Jun 2020 22:38:44 +0800 Subject: [PATCH 21/70] Change filename style. --- examples/Cargo.toml | 8 ++++---- examples/{echo-uds.rs => echo_uds.rs} | 0 examples/{echo-uds-client.rs => echo_uds_client.rs} | 0 3 files changed, 4 insertions(+), 4 deletions(-) rename examples/{echo-uds.rs => echo_uds.rs} (100%) rename examples/{echo-uds-client.rs => echo_uds_client.rs} (100%) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 31ec241..3561941 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -56,9 +56,9 @@ name = "redis" path = "redis.rs" [[example]] -name = "echo-uds" -path = "echo-uds.rs" +name = "echo_uds" +path = "echo_uds.rs" [[example]] -name = "echo-uds-client" -path = "echo-uds-client.rs" \ No newline at end of file +name = "echo_uds_client" +path = "echo_uds_client.rs" \ No newline at end of file diff --git a/examples/echo-uds.rs b/examples/echo_uds.rs similarity index 100% rename from examples/echo-uds.rs rename to examples/echo_uds.rs diff --git a/examples/echo-uds-client.rs b/examples/echo_uds_client.rs similarity index 100% rename from examples/echo-uds-client.rs rename to examples/echo_uds_client.rs From b748713cbba520c577c02789e9ac2216f229532e Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Thu, 11 Jun 2020 22:52:10 +0800 Subject: [PATCH 22/70] prepare release 0.5.3. --- README.md | 1 + examples/Cargo.toml | 9 ++++----- rsocket-benchmark/Cargo.toml | 8 ++++---- rsocket-messaging/Cargo.toml | 8 ++++---- rsocket-test/Cargo.toml | 8 ++++---- rsocket-transport-tcp/Cargo.toml | 2 +- rsocket-transport-tcp/README.md | 4 ++-- rsocket-transport-unix/Cargo.toml | 2 +- rsocket-transport-wasm/Cargo.toml | 2 +- rsocket-transport-websocket/Cargo.toml | 2 +- rsocket-transport-websocket/README.md | 4 ++-- rsocket/Cargo.toml | 1 - 12 files changed, 25 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 1c2b4b5..ce52ca5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # rsocket-rust +[![Build Status](https://travis-ci.com/rsocket/rsocket-rust.svg?branch=master)](https://travis-ci.com/rsocket/rsocket-rust) [![Crates.io](https://img.shields.io/crates/v/rsocket_rust)](https://crates.io/crates/rsocket_rust) [![Crates.io](https://img.shields.io/crates/d/rsocket_rust)](https://crates.io/crates/rsocket_rust) [![License](https://img.shields.io/github/license/rsocket/rsocket-rust.svg)](https://github.com/rsocket/rsocket-rust/blob/master/LICENSE) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 3561941..e5b1f1a 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -14,17 +14,16 @@ tokio-postgres = "0.5.4" redis = "0.16.0" [dev-dependencies.rsocket_rust] -path = "../rsocket" +version = "0.5.3" [dev-dependencies.rsocket_rust_transport_tcp] -path = "../rsocket-transport-tcp" +version = "0.5.3" [dev-dependencies.rsocket_rust_transport_unix] -path = "../rsocket-transport-unix" +version = "0.5.3" [dev-dependencies.rsocket_rust_transport_websocket] -version = "0.5.2" -path = "../rsocket-transport-websocket" +version = "0.5.3" [dev-dependencies.tokio] version = "0.2.21" diff --git a/rsocket-benchmark/Cargo.toml b/rsocket-benchmark/Cargo.toml index fc1af87..c39748b 100644 --- a/rsocket-benchmark/Cargo.toml +++ b/rsocket-benchmark/Cargo.toml @@ -17,17 +17,17 @@ serde_derive = "1.0.111" criterion = "0.3.2" [dev-dependencies.rsocket_rust] -path = "../rsocket" +version = "0.5.3" features = ["frame"] [dev-dependencies.rsocket_rust_transport_tcp] -path = "../rsocket-transport-tcp" +version = "0.5.3" [dev-dependencies.rsocket_rust_transport_websocket] -path = "../rsocket-transport-websocket" +version = "0.5.3" [dev-dependencies.rsocket_rust_messaging] -path = "../rsocket-messaging" +version = "0.5.3" [dev-dependencies.tokio] version = "0.2.21" diff --git a/rsocket-messaging/Cargo.toml b/rsocket-messaging/Cargo.toml index 15cd618..f360e47 100644 --- a/rsocket-messaging/Cargo.toml +++ b/rsocket-messaging/Cargo.toml @@ -13,17 +13,17 @@ description = "Communicate with Spring RSocket Messaging." futures = "0.3.5" bytes = "0.5.4" serde = "1.0.111" -serde_json = "1.0.53" +serde_json = "1.0.55" serde_cbor = "0.11.1" hex = "0.4.2" url = "2.1.1" [dependencies.rsocket_rust] -path = "../rsocket" +version = "0.5.3" features = ["frame"] [dependencies.rsocket_rust_transport_tcp] -path = "../rsocket-transport-tcp" +version = "0.5.3" [dependencies.rsocket_rust_transport_websocket] -path = "../rsocket-transport-websocket" +version = "0.5.3" \ No newline at end of file diff --git a/rsocket-test/Cargo.toml b/rsocket-test/Cargo.toml index 50e0fab..63f70bb 100644 --- a/rsocket-test/Cargo.toml +++ b/rsocket-test/Cargo.toml @@ -20,16 +20,16 @@ path = "../rsocket" features = ["frame"] [dev-dependencies.rsocket_rust_transport_tcp] -path = "../rsocket-transport-tcp" +version = "0.5.3" [dev-dependencies.rsocket_rust_transport_unix] -path = "../rsocket-transport-unix" +version = "0.5.3" [dev-dependencies.rsocket_rust_transport_websocket] -path = "../rsocket-transport-websocket" +version = "0.5.3" [dev-dependencies.rsocket_rust_messaging] -path = "../rsocket-messaging" +version = "0.5.3" [dev-dependencies.tokio] version = "0.2.21" diff --git a/rsocket-transport-tcp/Cargo.toml b/rsocket-transport-tcp/Cargo.toml index ed59a7a..a83bc9b 100644 --- a/rsocket-transport-tcp/Cargo.toml +++ b/rsocket-transport-tcp/Cargo.toml @@ -15,7 +15,7 @@ futures = "0.3.5" bytes = "0.5.4" [dependencies.rsocket_rust] -path = "../rsocket" +version = "0.5.3" features = ["frame"] [dependencies.tokio] diff --git a/rsocket-transport-tcp/README.md b/rsocket-transport-tcp/README.md index 666e7c7..b1333be 100644 --- a/rsocket-transport-tcp/README.md +++ b/rsocket-transport-tcp/README.md @@ -7,8 +7,8 @@ Add dependencies in your `Cargo.toml`. ```toml [dependencies] tokio = "0.2.21" -rsocket_rust = "0.5.2" -rsocket_rust_transport_tcp = "0.5.2" +rsocket_rust = "0.5.3" +rsocket_rust_transport_tcp = "0.5.3" ``` ### Server diff --git a/rsocket-transport-unix/Cargo.toml b/rsocket-transport-unix/Cargo.toml index bdb8f85..f4e5d2a 100644 --- a/rsocket-transport-unix/Cargo.toml +++ b/rsocket-transport-unix/Cargo.toml @@ -15,7 +15,7 @@ futures = "0.3.5" bytes = "0.5.4" [dependencies.rsocket_rust] -path = "../rsocket" +version = "0.5.3" features = ["frame"] [dependencies.tokio] diff --git a/rsocket-transport-wasm/Cargo.toml b/rsocket-transport-wasm/Cargo.toml index ec0aa2b..56b7b48 100644 --- a/rsocket-transport-wasm/Cargo.toml +++ b/rsocket-transport-wasm/Cargo.toml @@ -19,7 +19,7 @@ serde = "1.0.111" serde_derive = "1.0.111" [dependencies.rsocket_rust] -path = "../rsocket" +version = "0.5.3" features = ["frame"] [dependencies.wasm-bindgen] diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index 737f085..79cbb4f 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -17,7 +17,7 @@ url = "2.1.1" tokio-tungstenite = "0.10.1" [dependencies.rsocket_rust] -path = "../rsocket" +version = "0.5.3" features = ["frame"] [dependencies.tokio] diff --git a/rsocket-transport-websocket/README.md b/rsocket-transport-websocket/README.md index cfea04e..baa1ec3 100644 --- a/rsocket-transport-websocket/README.md +++ b/rsocket-transport-websocket/README.md @@ -7,8 +7,8 @@ Add dependencies in your `Cargo.toml`. ```toml [dependencies] tokio = "0.2.21" -rsocket_rust = "0.5.2" -rsocket_rust_transport_websocket = "0.5.2" +rsocket_rust = "0.5.3" +rsocket_rust_transport_websocket = "0.5.3" ``` ### Server diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index a174ad4..50479d4 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -14,7 +14,6 @@ log = "0.4.8" bytes = "0.5.4" futures = "0.3.5" lazy_static = "1.4.0" -async-trait = "0.1.33" [dependencies.tokio] version = "0.2.21" From e14df99c50f48cd44c1a38b96bc0b08560cc0574 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Thu, 11 Jun 2020 23:29:03 +0800 Subject: [PATCH 23/70] release v0.5.3 --- rsocket-test/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rsocket-test/Cargo.toml b/rsocket-test/Cargo.toml index 63f70bb..f86afcb 100644 --- a/rsocket-test/Cargo.toml +++ b/rsocket-test/Cargo.toml @@ -16,7 +16,7 @@ serde = "1.0.111" serde_derive = "1.0.111" [dev-dependencies.rsocket_rust] -path = "../rsocket" +version = "0.5.3" features = ["frame"] [dev-dependencies.rsocket_rust_transport_tcp] From 1322bd44a79569319879456157659dba3d52ca04 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Mon, 31 Aug 2020 22:09:36 +0800 Subject: [PATCH 24/70] Transport refinement. --- Cargo.toml | 3 +- examples/Cargo.toml | 27 +- examples/echo.rs | 161 +++++--- examples/echo_uds.rs | 28 -- examples/echo_uds_client.rs | 31 -- examples/postgres.rs | 17 +- examples/qps.rs | 141 +++++-- examples/redis.rs | 17 +- justfile | 13 +- rsocket-benchmark/Cargo.toml | 10 +- rsocket-messaging/Cargo.toml | 14 +- rsocket-messaging/src/requester.rs | 75 ++-- rsocket-test/Cargo.toml | 19 +- rsocket-test/tests/test_clients.rs | 43 +- rsocket-transport-tcp/Cargo.toml | 14 +- rsocket-transport-tcp/src/client.rs | 113 ------ rsocket-transport-tcp/src/client/mod.rs | 5 + rsocket-transport-tcp/src/client/tcp.rs | 69 ++++ rsocket-transport-tcp/src/client/uds.rs | 55 +++ rsocket-transport-tcp/src/codec.rs | 40 -- .../src/connection}/codec.rs | 10 +- rsocket-transport-tcp/src/connection/mod.rs | 6 + rsocket-transport-tcp/src/connection/tcp.rs | 64 +++ rsocket-transport-tcp/src/connection/uds.rs | 64 +++ rsocket-transport-tcp/src/lib.rs | 8 +- rsocket-transport-tcp/src/misc.rs | 17 + rsocket-transport-tcp/src/server.rs | 65 --- rsocket-transport-tcp/src/server/mod.rs | 5 + rsocket-transport-tcp/src/server/tcp.rs | 70 ++++ rsocket-transport-tcp/src/server/uds.rs | 69 ++++ rsocket-transport-unix/Cargo.toml | 29 -- rsocket-transport-unix/README.md | 85 ---- rsocket-transport-unix/src/client.rs | 113 ------ rsocket-transport-unix/src/lib.rs | 11 - rsocket-transport-unix/src/server.rs | 65 --- rsocket-transport-wasm/Cargo.toml | 19 +- rsocket-transport-wasm/src/client.rs | 120 +++--- rsocket-transport-wasm/src/connection.rs | 59 +++ rsocket-transport-wasm/src/lib.rs | 4 +- rsocket-transport-wasm/src/misc.rs | 6 +- rsocket-transport-wasm/src/runtime.rs | 15 - rsocket-transport-websocket/Cargo.toml | 13 +- rsocket-transport-websocket/src/client.rs | 79 +--- rsocket-transport-websocket/src/connection.rs | 78 ++++ rsocket-transport-websocket/src/lib.rs | 1 + rsocket-transport-websocket/src/server.rs | 96 +++-- rsocket/Cargo.toml | 16 +- rsocket/src/{x => core}/client.rs | 115 +++--- rsocket/src/core/factory.rs | 23 ++ rsocket/src/{x => core}/mod.rs | 2 + rsocket/src/core/server.rs | 146 +++++++ rsocket/src/error.rs | 2 + rsocket/src/extension/composite.rs | 23 +- rsocket/src/extension/mime.rs | 1 - rsocket/src/extension/routing.rs | 8 +- rsocket/src/frame/error.rs | 4 +- rsocket/src/frame/keepalive.rs | 4 +- rsocket/src/frame/lease.rs | 4 +- rsocket/src/frame/metadata_push.rs | 4 +- rsocket/src/frame/mod.rs | 8 +- rsocket/src/frame/payload.rs | 5 +- rsocket/src/frame/request_channel.rs | 4 +- rsocket/src/frame/request_fnf.rs | 4 +- rsocket/src/frame/request_n.rs | 4 +- rsocket/src/frame/request_response.rs | 4 +- rsocket/src/frame/request_stream.rs | 4 +- rsocket/src/frame/resume.rs | 4 +- rsocket/src/frame/resume_ok.rs | 4 +- rsocket/src/frame/setup.rs | 4 +- rsocket/src/frame/utils.rs | 8 +- rsocket/src/lib.rs | 8 +- rsocket/src/payload/normal.rs | 2 +- rsocket/src/prelude.rs | 6 +- rsocket/src/runtime/mod.rs | 24 +- rsocket/src/spi.rs | 46 +-- rsocket/src/transport/misc.rs | 1 - rsocket/src/transport/socket.rs | 370 +++++++----------- rsocket/src/transport/spi.rs | 68 ++-- rsocket/src/utils.rs | 2 - rsocket/src/x/factory.rs | 21 - rsocket/src/x/server.rs | 106 ----- 81 files changed, 1579 insertions(+), 1546 deletions(-) delete mode 100644 examples/echo_uds.rs delete mode 100644 examples/echo_uds_client.rs delete mode 100644 rsocket-transport-tcp/src/client.rs create mode 100644 rsocket-transport-tcp/src/client/mod.rs create mode 100644 rsocket-transport-tcp/src/client/tcp.rs create mode 100644 rsocket-transport-tcp/src/client/uds.rs delete mode 100644 rsocket-transport-tcp/src/codec.rs rename {rsocket-transport-unix/src => rsocket-transport-tcp/src/connection}/codec.rs (85%) create mode 100644 rsocket-transport-tcp/src/connection/mod.rs create mode 100644 rsocket-transport-tcp/src/connection/tcp.rs create mode 100644 rsocket-transport-tcp/src/connection/uds.rs create mode 100644 rsocket-transport-tcp/src/misc.rs delete mode 100644 rsocket-transport-tcp/src/server.rs create mode 100644 rsocket-transport-tcp/src/server/mod.rs create mode 100644 rsocket-transport-tcp/src/server/tcp.rs create mode 100644 rsocket-transport-tcp/src/server/uds.rs delete mode 100644 rsocket-transport-unix/Cargo.toml delete mode 100644 rsocket-transport-unix/README.md delete mode 100644 rsocket-transport-unix/src/client.rs delete mode 100644 rsocket-transport-unix/src/lib.rs delete mode 100644 rsocket-transport-unix/src/server.rs create mode 100644 rsocket-transport-wasm/src/connection.rs delete mode 100644 rsocket-transport-wasm/src/runtime.rs create mode 100644 rsocket-transport-websocket/src/connection.rs rename rsocket/src/{x => core}/client.rs (60%) create mode 100644 rsocket/src/core/factory.rs rename rsocket/src/{x => core}/mod.rs (76%) create mode 100644 rsocket/src/core/server.rs delete mode 100644 rsocket/src/x/factory.rs delete mode 100644 rsocket/src/x/server.rs diff --git a/Cargo.toml b/Cargo.toml index 2c68ae7..687b43b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,6 @@ members = [ "rsocket", # transports "rsocket-transport-tcp", -"rsocket-transport-unix", "rsocket-transport-websocket", "rsocket-transport-wasm", # extra @@ -13,5 +12,5 @@ members = [ # internal "examples", "rsocket-test", -"rsocket-benchmark", +# "rsocket-benchmark", ] diff --git a/examples/Cargo.toml b/examples/Cargo.toml index e5b1f1a..64df85b 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -6,27 +6,24 @@ edition = "2018" publish = false [dev-dependencies] -log = "0.4.8" +log = "0.4.11" env_logger = "0.7.1" futures = "0.3.5" -clap = "2.33.1" -tokio-postgres = "0.5.4" -redis = "0.16.0" +clap = "2.33.3" +tokio-postgres = "0.5.5" +redis = "0.17.0" [dev-dependencies.rsocket_rust] -version = "0.5.3" +path = "../rsocket" [dev-dependencies.rsocket_rust_transport_tcp] -version = "0.5.3" - -[dev-dependencies.rsocket_rust_transport_unix] -version = "0.5.3" +path = "../rsocket-transport-tcp" [dev-dependencies.rsocket_rust_transport_websocket] -version = "0.5.3" +path = "../rsocket-transport-websocket" [dev-dependencies.tokio] -version = "0.2.21" +version = "0.2.22" default-features = false features = ["full"] @@ -53,11 +50,3 @@ path = "postgres.rs" [[example]] name = "redis" path = "redis.rs" - -[[example]] -name = "echo_uds" -path = "echo_uds.rs" - -[[example]] -name = "echo_uds_client" -path = "echo_uds_client.rs" \ No newline at end of file diff --git a/examples/echo.rs b/examples/echo.rs index 9075313..b535fc5 100644 --- a/examples/echo.rs +++ b/examples/echo.rs @@ -3,10 +3,15 @@ extern crate log; use clap::{App, Arg, SubCommand}; use rsocket_rust::prelude::*; -use rsocket_rust_transport_tcp::{TcpClientTransport, TcpServerTransport}; -use std::error::Error; +use rsocket_rust::transport::Connection; +use rsocket_rust_transport_tcp::{ + TcpClientTransport, TcpServerTransport, UnixClientTransport, UnixServerTransport, +}; +use rsocket_rust_transport_websocket::{WebsocketClientTransport, WebsocketServerTransport}; use std::fs; +type Result = rsocket_rust::Result; + enum RequestMode { FNF, REQUEST, @@ -14,8 +19,76 @@ enum RequestMode { CHANNEL, } +async fn serve(transport: A, mtu: usize) -> Result<()> +where + A: Send + Sync + ServerTransport + 'static, + B: Send + Sync + Transport + 'static, +{ + RSocketFactory::receive() + .transport(transport) + .fragment(mtu) + .acceptor(Box::new(|setup, _socket| { + info!("accept setup: {:?}", setup); + Ok(Box::new(EchoRSocket)) + // Or you can reject setup + // Err(From::from("SETUP_NOT_ALLOW")) + })) + .on_start(Box::new(|| info!("+++++++ echo server started! +++++++"))) + .serve() + .await +} + +async fn connect(transport: A, mtu: usize, req: Payload, mode: RequestMode) -> Result<()> +where + A: Send + Sync + Transport + 'static, + B: Send + Sync + Connection + 'static, +{ + let cli = RSocketFactory::connect() + .fragment(mtu) + .transport(transport) + .start() + .await?; + + match mode { + RequestMode::FNF => { + cli.fire_and_forget(req).await; + } + RequestMode::STREAM => { + let mut results = cli.request_stream(req); + loop { + match results.next().await { + Some(Ok(v)) => info!("{:?}", v), + Some(Err(e)) => { + error!("STREAM_RESPONSE FAILED: {:?}", e); + break; + } + None => break, + } + } + } + RequestMode::CHANNEL => { + let mut results = cli.request_channel(Box::pin(futures::stream::iter(vec![Ok(req)]))); + loop { + match results.next().await { + Some(Ok(v)) => info!("{:?}", v), + Some(Err(e)) => { + error!("CHANNEL_RESPONSE FAILED: {:?}", e); + break; + } + None => break, + } + } + } + RequestMode::REQUEST => { + let res = cli.request_response(req).await.expect("Request failed!"); + info!("{:?}", res); + } + } + Ok(()) +} + #[tokio::main] -async fn main() -> Result<(), Box> { +async fn main() -> Result<()> { env_logger::builder().format_timestamp_millis().init(); let cli = App::new("echo") @@ -106,18 +179,25 @@ async fn main() -> Result<(), Box> { .value_of("mtu") .map(|it| it.parse().expect("Invalid mtu string!")) .unwrap_or(0); - RSocketFactory::receive() - .transport(TcpServerTransport::from(addr)) - .fragment(mtu) - .acceptor(Box::new(|setup, _socket| { - info!("accept setup: {:?}", setup); - Ok(Box::new(EchoRSocket)) - // Or you can reject setup - // Err(From::from("SETUP_NOT_ALLOW")) - })) - .on_start(Box::new(|| info!("+++++++ echo server started! +++++++"))) - .serve() - .await + + if addr.starts_with("ws://") { + serve(WebsocketServerTransport::from(addr), mtu).await + } else if addr.starts_with("unix://") { + let addr_owned = addr.to_owned(); + tokio::spawn(async move { + let _ = serve(UnixServerTransport::from(addr_owned), mtu).await; + }); + let sockfile = addr.chars().skip(7).collect::(); + // Watch signal + tokio::signal::ctrl_c().await?; + info!("ctrl-c received!"); + if let Err(e) = std::fs::remove_file(&sockfile) { + error!("remove unix sock file failed: {}", e); + } + Ok(()) + } else { + serve(TcpServerTransport::from(addr), mtu).await + } } ("connect", Some(flags)) => { let mut modes: Vec = vec![]; @@ -147,12 +227,6 @@ async fn main() -> Result<(), Box> { .unwrap_or(0); let addr = flags.value_of("URL").expect("Missing URL"); - let cli = RSocketFactory::connect() - .fragment(mtu) - .transport(TcpClientTransport::from(addr)) - .start() - .await - .expect("Connect failed!"); let mut bu = Payload::builder(); if let Some(data) = flags.value_of("input") { if data.starts_with("@") { @@ -164,45 +238,14 @@ async fn main() -> Result<(), Box> { } } let req = bu.build(); - - match modes.pop().unwrap_or(RequestMode::REQUEST) { - RequestMode::FNF => { - cli.fire_and_forget(req).await; - } - RequestMode::STREAM => { - let mut results = cli.request_stream(req); - loop { - match results.next().await { - Some(Ok(v)) => info!("{:?}", v), - Some(Err(e)) => { - error!("STREAM_RESPONSE FAILED: {:?}", e); - break; - } - None => break, - } - } - } - RequestMode::CHANNEL => { - let mut results = - cli.request_channel(Box::pin(futures::stream::iter(vec![Ok(req)]))); - loop { - match results.next().await { - Some(Ok(v)) => info!("{:?}", v), - Some(Err(e)) => { - error!("CHANNEL_RESPONSE FAILED: {:?}", e); - break; - } - None => break, - } - } - } - RequestMode::REQUEST => { - let res = cli.request_response(req).await.expect("Request failed!"); - info!("{:?}", res); - } + let mode = modes.pop().unwrap_or(RequestMode::REQUEST); + if addr.starts_with("ws://") { + connect(WebsocketClientTransport::from(addr), mtu, req, mode).await + } else if addr.starts_with("unix://") { + connect(UnixClientTransport::from(addr), mtu, req, mode).await + } else { + connect(TcpClientTransport::from(addr), mtu, req, mode).await } - - Ok(()) } _ => Ok(()), } diff --git a/examples/echo_uds.rs b/examples/echo_uds.rs deleted file mode 100644 index ecd6477..0000000 --- a/examples/echo_uds.rs +++ /dev/null @@ -1,28 +0,0 @@ -use log::info; -use rsocket_rust::prelude::{EchoRSocket, RSocketFactory, ServerResponder}; -use rsocket_rust_transport_unix::UnixServerTransport; -use std::error::Error; - -#[tokio::main] -async fn main() -> Result<(), Box> { - let transport: UnixServerTransport = UnixServerTransport::from("/tmp/rsocket-uds.sock"); - - let responder: ServerResponder = Box::new(|setup, _socket| { - info!("accept setup: {:?}", setup); - Ok(Box::new(EchoRSocket)) - // Or you can reject setup - // Err(From::from("SETUP_NOT_ALLOW")) - }); - - let on_start: Box = - Box::new(|| info!("+++++++ echo server started! +++++++")); - - RSocketFactory::receive() - .transport(transport) - .acceptor(responder) - .on_start(on_start) - .serve() - .await?; - - Ok(()) -} diff --git a/examples/echo_uds_client.rs b/examples/echo_uds_client.rs deleted file mode 100644 index e075de4..0000000 --- a/examples/echo_uds_client.rs +++ /dev/null @@ -1,31 +0,0 @@ -use log::info; -use rsocket_rust::prelude::{ClientResponder, EchoRSocket, Payload, RSocket, RSocketFactory}; -use rsocket_rust_transport_unix::UnixClientTransport; -use std::error::Error; - -#[tokio::main] -async fn main() -> Result<(), Box> { - let responder: ClientResponder = Box::new(|| Box::new(EchoRSocket)); - - let client = RSocketFactory::connect() - .acceptor(responder) - .transport(UnixClientTransport::from("/tmp/rsocket-uds.sock")) - .setup(Payload::from("READY!")) - .mime_type("text/plain", "text/plain") - .start() - .await - .unwrap(); - - let request_payload: Payload = Payload::builder() - .set_data_utf8("Hello World!") - .set_metadata_utf8("Rust") - .build(); - - let res = client.request_response(request_payload).await.unwrap(); - - info!("got: {:?}", res); - - client.close(); - - Ok(()) -} diff --git a/examples/postgres.rs b/examples/postgres.rs index f940bb5..bf79b84 100644 --- a/examples/postgres.rs +++ b/examples/postgres.rs @@ -1,14 +1,14 @@ #[macro_use] extern crate log; -use rsocket_rust::{error::RSocketError, prelude::*}; +use rsocket_rust::prelude::*; +use rsocket_rust::Result; use rsocket_rust_transport_tcp::TcpServerTransport; -use std::error::Error; use std::sync::Arc; use tokio_postgres::{Client as PgClient, NoTls}; #[tokio::main] -async fn main() -> Result<(), Box> { +async fn main() -> Result<()> { env_logger::builder().format_timestamp_millis().init(); let dao = Dao::try_new().await?; RSocketFactory::receive() @@ -25,7 +25,7 @@ struct Dao { } impl RSocket for Dao { - fn request_response(&self, _: Payload) -> Mono> { + fn request_response(&self, _: Payload) -> Mono> { let client = self.client.clone(); Box::pin(async move { let row = client @@ -45,20 +45,17 @@ impl RSocket for Dao { unimplemented!() } - fn request_stream(&self, _: Payload) -> Flux> { + fn request_stream(&self, _: Payload) -> Flux> { unimplemented!() } - fn request_channel( - &self, - _: Flux>, - ) -> Flux> { + fn request_channel(&self, _: Flux>) -> Flux> { unimplemented!() } } impl Dao { - async fn try_new() -> Result> { + async fn try_new() -> Result { let (client, connection) = tokio_postgres::connect("host=localhost user=postgres password=postgres", NoTls) .await?; diff --git a/examples/qps.rs b/examples/qps.rs index c18053e..2fbce66 100644 --- a/examples/qps.rs +++ b/examples/qps.rs @@ -1,61 +1,148 @@ #[macro_use] extern crate log; +use clap::{App, Arg}; use rsocket_rust::prelude::*; -use rsocket_rust_transport_tcp::TcpClientTransport; +use rsocket_rust::transport::{Connection, Transport}; +use rsocket_rust_transport_tcp::{TcpClientTransport, UnixClientTransport}; +use rsocket_rust_transport_websocket::WebsocketClientTransport; use std::error::Error; use std::sync::{ atomic::{AtomicU32, Ordering}, Arc, }; use std::time::SystemTime; -use tokio::runtime::Runtime; -use tokio::sync::Notify; +use tokio::sync::{oneshot, Notify}; -const TOTAL: u32 = 1_000_000; +async fn connect( + started: oneshot::Sender, + transport: A, + count: u32, + payload_size: usize, + notify: Arc, +) -> Result<(), Box> +where + A: Send + Sync + Transport + 'static, + B: Send + Sync + Connection + 'static, +{ + let client = RSocketFactory::connect() + .transport(transport) + .start() + .await?; -fn main() -> Result<(), Box> { - env_logger::builder().format_timestamp_millis().init(); - - let mut rt = Runtime::new()?; - let client = rt.block_on(async { - RSocketFactory::connect() - .transport(TcpClientTransport::from("127.0.0.1:7878")) - .start() - .await - })?; - // simulate 1KB payload. + // simulate customize size payload. let req = Payload::builder() - .set_data_utf8("X".repeat(1024).as_ref()) + .set_data_utf8("_".repeat(payload_size).as_ref()) .build(); - let counter = Arc::new(AtomicU32::new(0)); let start_time = SystemTime::now(); - let notify = Arc::new(Notify::new()); - for _ in 0..TOTAL { + let counter = Arc::new(AtomicU32::new(0)); + + for _ in 0..count { let client = client.clone(); let counter = counter.clone(); let notify = notify.clone(); let req = req.clone(); - rt.spawn(async move { - client.request_response(req).await.expect("Request failed"); + tokio::spawn(async move { + if let Err(e) = client.request_response(req).await { + error!("request failed: {}", e); + } let current = counter.fetch_add(1, Ordering::SeqCst) + 1; - if current >= TOTAL { + if current >= count { notify.notify(); } }); } - rt.block_on(async move { - notify.notified().await; - }); + started.send(start_time).unwrap(); + Ok(()) +} + +#[tokio::main] +async fn main() -> Result<(), Box> { + env_logger::builder().format_timestamp_millis().init(); + + let cli = App::new("echo") + .version("0.0.0") + .author("Jeffsky ") + .about("An QPS benchmark tool for RSocket.") + .arg( + Arg::with_name("count") + .short("c") + .long("count") + .required(false) + .takes_value(true) + .default_value("1000000") + .help("Requests counts."), + ) + .arg( + Arg::with_name("size") + .short("s") + .long("size") + .required(false) + .takes_value(true) + .default_value("1024") + .help("Data size."), + ) + .arg( + Arg::with_name("URL") + .required(false) + .index(1) + .default_value("127.0.0.1:7878") + .help("Connect url"), + ) + .get_matches(); + + let count: u32 = cli + .value_of("count") + .map(|s| s.parse().expect("Invalid count!")) + .unwrap(); + let size: usize = cli + .value_of("size") + .map(|s| s.parse().expect("Invalid size!")) + .unwrap(); + let addr = cli.value_of("URL").unwrap(); + + let notify = Arc::new(Notify::new()); + let (started_tx, started_rx) = oneshot::channel::(); + + if addr.starts_with("ws://") { + connect( + started_tx, + WebsocketClientTransport::from(addr), + count, + size, + notify.clone(), + ) + .await?; + } else if addr.starts_with("unix://") { + connect( + started_tx, + UnixClientTransport::from(addr), + count, + size, + notify.clone(), + ) + .await?; + } else { + connect( + started_tx, + TcpClientTransport::from(addr), + count, + size, + notify.clone(), + ) + .await?; + } + notify.notified().await; + let start_time = started_rx.await.unwrap(); let costs = SystemTime::now() .duration_since(start_time) .unwrap() .as_millis(); info!( "total={}, cost={}ms, qps={}", - TOTAL, + count, costs, - 1000f64 * (TOTAL as f64) / (costs as f64) + 1000f64 * (count as f64) / (costs as f64) ); Ok(()) } diff --git a/examples/redis.rs b/examples/redis.rs index e19d9d8..b268616 100644 --- a/examples/redis.rs +++ b/examples/redis.rs @@ -1,7 +1,7 @@ use redis::Client as RedisClient; -use rsocket_rust::{error::RSocketError, prelude::*}; +use rsocket_rust::prelude::*; +use rsocket_rust::Result; use rsocket_rust_transport_tcp::TcpServerTransport; -use std::error::Error; use std::str::FromStr; #[derive(Clone)] @@ -10,7 +10,7 @@ struct RedisDao { } #[tokio::main] -async fn main() -> Result<(), Box> { +async fn main() -> Result<()> { let dao = RedisDao::from_str("redis://127.0.0.1").expect("Connect redis failed!"); RSocketFactory::receive() .acceptor(Box::new(move |_setup, _socket| Ok(Box::new(dao.clone())))) @@ -22,14 +22,14 @@ async fn main() -> Result<(), Box> { impl FromStr for RedisDao { type Err = redis::RedisError; - fn from_str(s: &str) -> Result { + fn from_str(s: &str) -> std::result::Result { let client = redis::Client::open(s)?; Ok(RedisDao { inner: client }) } } impl RSocket for RedisDao { - fn request_response(&self, req: Payload) -> Mono> { + fn request_response(&self, req: Payload) -> Mono> { let client = self.inner.clone(); Box::pin(async move { @@ -52,13 +52,10 @@ impl RSocket for RedisDao { fn fire_and_forget(&self, _req: Payload) -> Mono<()> { unimplemented!() } - fn request_stream(&self, _req: Payload) -> Flux> { + fn request_stream(&self, _req: Payload) -> Flux> { unimplemented!() } - fn request_channel( - &self, - _reqs: Flux>, - ) -> Flux> { + fn request_channel(&self, _reqs: Flux>) -> Flux> { unimplemented!() } } diff --git a/justfile b/justfile index 3193f9f..5d883f0 100644 --- a/justfile +++ b/justfile @@ -1,4 +1,13 @@ -default: - echo 'Hello, world!' +alias b := bench +alias e := echo + +build: + @cargo build test: @cargo test -- --nocapture +lint: + @cargo clippy +echo: + @RUST_LOG=release cargo run --release --example echo -- serve tcp://127.0.0.1:7878 +bench: + @RUST_LOG=info cargo run --release --example qps -- -c 1000000 -s 1024 tcp://127.0.0.1:7878 diff --git a/rsocket-benchmark/Cargo.toml b/rsocket-benchmark/Cargo.toml index c39748b..4441f68 100644 --- a/rsocket-benchmark/Cargo.toml +++ b/rsocket-benchmark/Cargo.toml @@ -9,12 +9,12 @@ publish = false log = "0.4" futures = "0.3.5" env_logger = "0.7.1" -bytes = "0.5.4" +bytes = "0.5.6" hex = "0.4.2" rand = "0.7.3" -serde = "1.0.111" -serde_derive = "1.0.111" -criterion = "0.3.2" +serde = "1.0.116" +serde_derive = "1.0.116" +criterion = "0.3.3" [dev-dependencies.rsocket_rust] version = "0.5.3" @@ -30,7 +30,7 @@ version = "0.5.3" version = "0.5.3" [dev-dependencies.tokio] -version = "0.2.21" +version = "0.2.22" default-features = false features = ["full"] diff --git a/rsocket-messaging/Cargo.toml b/rsocket-messaging/Cargo.toml index f360e47..b17d917 100644 --- a/rsocket-messaging/Cargo.toml +++ b/rsocket-messaging/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_messaging" -version = "0.5.3" +version = "0.6.0" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" @@ -11,19 +11,19 @@ description = "Communicate with Spring RSocket Messaging." [dependencies] futures = "0.3.5" -bytes = "0.5.4" -serde = "1.0.111" -serde_json = "1.0.55" +bytes = "0.5.6" +serde = "1.0.116" +serde_json = "1.0.57" serde_cbor = "0.11.1" hex = "0.4.2" url = "2.1.1" [dependencies.rsocket_rust] -version = "0.5.3" +path = "../rsocket" features = ["frame"] [dependencies.rsocket_rust_transport_tcp] -version = "0.5.3" +path = "../rsocket-transport-tcp" [dependencies.rsocket_rust_transport_websocket] -version = "0.5.3" \ No newline at end of file +path = "../rsocket-transport-websocket" diff --git a/rsocket-messaging/src/requester.rs b/rsocket-messaging/src/requester.rs index b88262e..ee9ce78 100644 --- a/rsocket-messaging/src/requester.rs +++ b/rsocket-messaging/src/requester.rs @@ -1,26 +1,22 @@ use super::misc::{self, marshal, unmarshal}; use bytes::{Bytes, BytesMut}; -use rsocket_rust::error::RSocketError; use rsocket_rust::extension::{CompositeMetadata, MimeType, RoutingMetadata}; use rsocket_rust::prelude::*; use rsocket_rust::utils::Writeable; +use rsocket_rust::Result; use rsocket_rust_transport_tcp::TcpClientTransport; use rsocket_rust_transport_websocket::WebsocketClientTransport; use serde::{de::DeserializeOwned, Serialize}; use std::collections::LinkedList; -use std::error::Error; use std::net::SocketAddr; -use std::result::Result; use std::sync::Arc; use url::Url; -type FnMetadata = Box Result<(MimeType, Vec), Box>>; -type FnData = Box Result, Box>>; -type PreflightResult = - Result<(Payload, MimeType, Arc>), Box>; -type UnpackerResult = Result<(MimeType, Payload), Box>; -type UnpackersResult = - Result<(MimeType, Flux>), Box>; +type FnMetadata = Box Result<(MimeType, Vec)>>; +type FnData = Box Result>>; +type PreflightResult = Result<(Payload, MimeType, Arc>)>; +type UnpackerResult = Result<(MimeType, Payload)>; +type UnpackersResult = Result<(MimeType, Flux>)>; enum TransportKind { TCP(String, u16), @@ -122,7 +118,7 @@ impl RequesterBuilder { self } - pub async fn build(self) -> Result> { + pub async fn build(self) -> Result { let data_mime_type = self.data_mime_type.unwrap_or(MimeType::APPLICATION_JSON); let mut added = 0usize; @@ -261,14 +257,10 @@ impl RequestSpec { self } - pub async fn retrieve(self) -> Result<(), Box> { - match self.preflight() { - Ok((req, _mime_type, rsocket)) => { - rsocket.fire_and_forget(req).await; - Ok(()) - } - Err(e) => Err(e), - } + pub async fn retrieve(self) -> Result<()> { + let (req, _mime_type, rsocket) = self.preflight()?; + rsocket.fire_and_forget(req).await; + Ok(()) } pub async fn retrieve_mono(self) -> Unpacker { @@ -279,9 +271,7 @@ impl RequestSpec { Ok(v) => Unpacker { inner: Ok((mime_type, v)), }, - Err(e) => Unpacker { - inner: Err(e.into()), - }, + Err(e) => Unpacker { inner: Err(e) }, } } Err(e) => Unpacker { inner: Err(e) }, @@ -321,44 +311,36 @@ impl RequestSpec { } impl Unpackers { - pub async fn block(self) -> Result, Box> + pub async fn block(self) -> Result> where T: Sized + DeserializeOwned, { let (mime_type, mut results) = self.inner?; let mut res = Vec::new(); while let Some(next) = results.next().await { - match next { - Ok(v) => { - if let Some(data) = v.data() { - let t = do_unmarshal::(&mime_type, data)?; - if let Some(t) = t { - res.push(t); - } - } + let v = next?; + if let Some(data) = v.data() { + let t = do_unmarshal::(&mime_type, data)?; + if let Some(t) = t { + res.push(t); } - Err(e) => return Err(e.into()), } } Ok(res) } - pub async fn foreach(self, callback: impl Fn(T)) -> Result<(), Box> + pub async fn foreach(self, callback: impl Fn(T)) -> Result<()> where T: Sized + DeserializeOwned, { let (mime_type, mut results) = self.inner?; while let Some(next) = results.next().await { - match next { - Ok(v) => { - if let Some(data) = v.data() { - let t = do_unmarshal::(&mime_type, data)?; - if let Some(t) = t { - callback(t); - } - } + let v = next?; + if let Some(data) = v.data() { + let t = do_unmarshal::(&mime_type, data)?; + if let Some(t) = t { + callback(t); } - Err(e) => return Err(format!("{}", e).into()), } } Ok(()) @@ -366,7 +348,7 @@ impl Unpackers { } impl Unpacker { - pub fn block(self) -> Result, Box> + pub fn block(self) -> Result> where T: Sized + DeserializeOwned, { @@ -378,10 +360,7 @@ impl Unpacker { } } -fn do_unmarshal( - mime_type: &MimeType, - raw: &Bytes, -) -> Result, Box> +fn do_unmarshal(mime_type: &MimeType, raw: &Bytes) -> Result> where T: Sized + DeserializeOwned, { @@ -393,7 +372,7 @@ where } } -fn do_marshal(mime_type: &MimeType, data: &T) -> Result, Box> +fn do_marshal(mime_type: &MimeType, data: &T) -> Result> where T: Sized + Serialize, { diff --git a/rsocket-test/Cargo.toml b/rsocket-test/Cargo.toml index f86afcb..de7a312 100644 --- a/rsocket-test/Cargo.toml +++ b/rsocket-test/Cargo.toml @@ -9,29 +9,26 @@ publish = false log = "0.4" futures = "0.3.5" env_logger = "0.7.1" -bytes = "0.5.4" +bytes = "0.5.6" hex = "0.4.2" rand = "0.7.3" -serde = "1.0.111" -serde_derive = "1.0.111" +serde = "1.0.116" +serde_derive = "1.0.116" [dev-dependencies.rsocket_rust] -version = "0.5.3" +path = "../rsocket" features = ["frame"] [dev-dependencies.rsocket_rust_transport_tcp] -version = "0.5.3" - -[dev-dependencies.rsocket_rust_transport_unix] -version = "0.5.3" +path = "../rsocket-transport-tcp" [dev-dependencies.rsocket_rust_transport_websocket] -version = "0.5.3" +path = "../rsocket-transport-websocket" [dev-dependencies.rsocket_rust_messaging] -version = "0.5.3" +path = "../rsocket-messaging" [dev-dependencies.tokio] -version = "0.2.21" +version = "0.2.22" default-features = false features = ["full"] diff --git a/rsocket-test/tests/test_clients.rs b/rsocket-test/tests/test_clients.rs index e8062cb..216b33a 100644 --- a/rsocket-test/tests/test_clients.rs +++ b/rsocket-test/tests/test_clients.rs @@ -3,8 +3,10 @@ extern crate log; use futures::stream; use rsocket_rust::prelude::*; -use rsocket_rust_transport_tcp::{TcpClientTransport, TcpServerTransport}; -use rsocket_rust_transport_unix::{UnixClientTransport, UnixServerTransport}; +use rsocket_rust::Client; +use rsocket_rust_transport_tcp::{ + TcpClientTransport, TcpServerTransport, UnixClientTransport, UnixServerTransport, +}; use rsocket_rust_transport_websocket::{WebsocketClientTransport, WebsocketServerTransport}; use std::thread::sleep; use std::time::Duration; @@ -131,7 +133,7 @@ fn test_unix() { // spawn a server server_runtime.spawn(async move { - RSocketFactory::receive() + if let Err(e) = RSocketFactory::receive() .transport(UnixServerTransport::from(addr)) .acceptor(Box::new(|setup, _socket| { info!("accept setup: {:?}", setup); @@ -142,6 +144,16 @@ fn test_unix() { })) .serve() .await + { + error!("server stopped with error: {}", e) + } + + // Watch signal + tokio::signal::ctrl_c().await.unwrap(); + info!("ctrl-c received!"); + if let Err(e) = std::fs::remove_file(addr) { + error!("remove unix sock file failed: {}", e); + } }); sleep(Duration::from_millis(500)); @@ -191,10 +203,7 @@ async fn test_request_response_err() { }; } -async fn exec_request_response(socket: &Client) -where - R: Send + Sync + Copy + Spawner + 'static, -{ +async fn exec_request_response(socket: &Client) { // request response let sending = Payload::builder() .set_data_utf8("Hello World!") @@ -204,28 +213,19 @@ where info!("REQUEST_RESPONSE: {:?}", result); } -async fn exec_metadata_push(socket: &Client) -where - R: Send + Sync + Copy + Spawner + 'static, -{ +async fn exec_metadata_push(socket: &Client) { let pa = Payload::builder().set_metadata_utf8("Hello World!").build(); // metadata push socket.metadata_push(pa).await; } -async fn exec_fire_and_forget(socket: &Client) -where - R: Send + Sync + Copy + Spawner + 'static, -{ +async fn exec_fire_and_forget(socket: &Client) { // request fnf let fnf = Payload::from("Hello World!"); socket.fire_and_forget(fnf).await; } -async fn exec_request_stream(socket: &Client) -where - R: Send + Sync + Copy + Spawner + 'static, -{ +async fn exec_request_stream(socket: &Client) { // request stream let sending = Payload::builder() .set_data_utf8("Hello Rust!") @@ -242,10 +242,7 @@ where } } -async fn exec_request_channel(socket: &Client) -where - R: Send + Sync + Copy + Spawner + 'static, -{ +async fn exec_request_channel(socket: &Client) { let sends: Vec<_> = (0..10) .map(|n| { let p = Payload::builder() diff --git a/rsocket-transport-tcp/Cargo.toml b/rsocket-transport-tcp/Cargo.toml index a83bc9b..5cf1c61 100644 --- a/rsocket-transport-tcp/Cargo.toml +++ b/rsocket-transport-tcp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_tcp" -version = "0.5.3" +version = "0.6.0" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" @@ -10,21 +10,21 @@ homepage = "https://github.com/rsocket/rsocket-rust" description = "TCP RSocket transport implementation." [dependencies] -log = "0.4.8" +log = "0.4.11" futures = "0.3.5" -bytes = "0.5.4" +bytes = "0.5.6" +async-trait = "0.1.40" [dependencies.rsocket_rust] -version = "0.5.3" +path = "../rsocket" features = ["frame"] [dependencies.tokio] -version = "0.2.21" +version = "0.2.22" default-features = false -features = [ "rt-core", "rt-threaded", "tcp", "sync", "stream" ] +features = [ "rt-core", "rt-threaded", "tcp", "uds", "sync", "dns", "stream", "io-util", "macros" ] [dependencies.tokio-util] version = "0.3.1" default-features = false features = ["codec"] - diff --git a/rsocket-transport-tcp/src/client.rs b/rsocket-transport-tcp/src/client.rs deleted file mode 100644 index e6ff764..0000000 --- a/rsocket-transport-tcp/src/client.rs +++ /dev/null @@ -1,113 +0,0 @@ -use super::codec::LengthBasedFrameCodec; -use futures::{SinkExt, StreamExt}; -use rsocket_rust::error::RSocketError; -use rsocket_rust::frame::Frame; -use rsocket_rust::runtime::{DefaultSpawner, Spawner}; -use rsocket_rust::transport::{ClientTransport, Rx, Tx, TxOnce}; -use std::net::{AddrParseError, SocketAddr, TcpStream as StdTcpStream}; -use std::str::FromStr; -use tokio::net::TcpStream; -use tokio_util::codec::Framed; - -enum Connector { - Direct(TcpStream), - Lazy(SocketAddr), -} - -pub struct TcpClientTransport { - connector: Connector, -} - -impl TcpClientTransport { - #[inline] - fn new(connector: Connector) -> TcpClientTransport { - TcpClientTransport { connector } - } - - #[inline] - async fn connect(self) -> Result { - match self.connector { - Connector::Direct(stream) => Ok(stream), - Connector::Lazy(addr) => match StdTcpStream::connect(&addr) { - Ok(raw) => match TcpStream::from_std(raw) { - Ok(stream) => Ok(stream), - Err(e) => Err(RSocketError::from(e)), - }, - Err(e) => Err(RSocketError::from(e)), - }, - } - } -} - -impl ClientTransport for TcpClientTransport { - fn attach( - self, - incoming: Tx, - mut sending: Rx, - connected: Option>>, - ) { - DefaultSpawner.spawn(async move { - match self.connect().await { - Ok(socket) => { - if let Some(sender) = connected { - sender.send(Ok(())).unwrap(); - } - let (mut writer, mut reader) = - Framed::new(socket, LengthBasedFrameCodec).split(); - DefaultSpawner.spawn(async move { - while let Some(it) = reader.next().await { - incoming.unbounded_send(it.unwrap()).unwrap(); - } - }); - // loop write - while let Some(it) = sending.next().await { - debug!("===> SND: {:?}", &it); - writer.send(it).await.unwrap() - } - } - Err(e) => { - if let Some(sender) = connected { - sender.send(Err(e)).unwrap(); - } - } - } - }); - } -} - -impl FromStr for TcpClientTransport { - type Err = AddrParseError; - - fn from_str(addr: &str) -> Result { - let socket_addr = if addr.starts_with("tcp://") || addr.starts_with("TCP://") { - addr.chars().skip(6).collect::().parse()? - } else { - addr.parse()? - }; - Ok(TcpClientTransport::new(Connector::Lazy(socket_addr))) - } -} - -impl From for TcpClientTransport { - fn from(addr: SocketAddr) -> TcpClientTransport { - TcpClientTransport::new(Connector::Lazy(addr)) - } -} - -impl From<&str> for TcpClientTransport { - fn from(addr: &str) -> TcpClientTransport { - let socket_addr: SocketAddr = if addr.starts_with("tcp://") || addr.starts_with("TCP://") { - addr.chars().skip(6).collect::().parse() - } else { - addr.parse() - } - .expect("Invalid transport string!"); - TcpClientTransport::new(Connector::Lazy(socket_addr)) - } -} - -impl From for TcpClientTransport { - fn from(socket: TcpStream) -> TcpClientTransport { - TcpClientTransport::new(Connector::Direct(socket)) - } -} diff --git a/rsocket-transport-tcp/src/client/mod.rs b/rsocket-transport-tcp/src/client/mod.rs new file mode 100644 index 0000000..6159817 --- /dev/null +++ b/rsocket-transport-tcp/src/client/mod.rs @@ -0,0 +1,5 @@ +mod tcp; +mod uds; + +pub use tcp::TcpClientTransport; +pub use uds::UnixClientTransport; diff --git a/rsocket-transport-tcp/src/client/tcp.rs b/rsocket-transport-tcp/src/client/tcp.rs new file mode 100644 index 0000000..d9c4af6 --- /dev/null +++ b/rsocket-transport-tcp/src/client/tcp.rs @@ -0,0 +1,69 @@ +use crate::{connection::TcpConnection, misc::parse_tcp_addr}; +use async_trait::async_trait; +use rsocket_rust::{transport::Transport, Result}; +use std::net::SocketAddr; +use tokio::net::TcpStream; + +#[derive(Debug)] +enum Connector { + Direct(TcpStream), + Lazy(SocketAddr), +} + +#[derive(Debug)] +pub struct TcpClientTransport { + connector: Connector, +} + +#[async_trait] +impl Transport for TcpClientTransport { + type Conn = TcpConnection; + + async fn connect(self) -> Result { + match self.connector { + Connector::Direct(socket) => Ok(TcpConnection::from(socket)), + Connector::Lazy(addr) => match TcpStream::connect(addr).await { + Ok(stream) => Ok(TcpConnection::from(stream)), + Err(e) => Err(Box::new(e)), + }, + } + } +} + +impl From for TcpClientTransport { + fn from(socket: TcpStream) -> TcpClientTransport { + TcpClientTransport { + connector: Connector::Direct(socket), + } + } +} + +impl From for TcpClientTransport { + fn from(addr: SocketAddr) -> TcpClientTransport { + TcpClientTransport { + connector: Connector::Lazy(addr), + } + } +} + +impl From for TcpClientTransport { + fn from(addr: String) -> Self { + let socket_addr: SocketAddr = parse_tcp_addr(addr) + .parse() + .expect("Invalid transport string!"); + TcpClientTransport { + connector: Connector::Lazy(socket_addr), + } + } +} + +impl From<&str> for TcpClientTransport { + fn from(addr: &str) -> TcpClientTransport { + let socket_addr: SocketAddr = parse_tcp_addr(addr) + .parse() + .expect("Invalid transport string!"); + TcpClientTransport { + connector: Connector::Lazy(socket_addr), + } + } +} diff --git a/rsocket-transport-tcp/src/client/uds.rs b/rsocket-transport-tcp/src/client/uds.rs new file mode 100644 index 0000000..91779fe --- /dev/null +++ b/rsocket-transport-tcp/src/client/uds.rs @@ -0,0 +1,55 @@ +use crate::connection::UnixConnection; +use crate::misc::parse_uds_addr; +use async_trait::async_trait; +use rsocket_rust::{transport::Transport, Result}; +use tokio::net::UnixStream; + +#[derive(Debug)] +enum Connector { + Direct(UnixStream), + Lazy(String), +} + +#[derive(Debug)] +pub struct UnixClientTransport { + connector: Connector, +} + +#[async_trait] +impl Transport for UnixClientTransport { + type Conn = UnixConnection; + + async fn connect(self) -> Result { + match self.connector { + Connector::Direct(socket) => Ok(UnixConnection::from(socket)), + Connector::Lazy(addr) => match UnixStream::connect(addr).await { + Ok(stream) => Ok(UnixConnection::from(stream)), + Err(e) => Err(Box::new(e)), + }, + } + } +} + +impl From for UnixClientTransport { + fn from(socket: UnixStream) -> UnixClientTransport { + UnixClientTransport { + connector: Connector::Direct(socket), + } + } +} + +impl From for UnixClientTransport { + fn from(addr: String) -> UnixClientTransport { + UnixClientTransport { + connector: Connector::Lazy(parse_uds_addr(addr)), + } + } +} + +impl From<&str> for UnixClientTransport { + fn from(addr: &str) -> UnixClientTransport { + UnixClientTransport { + connector: Connector::Lazy(parse_uds_addr(addr)), + } + } +} diff --git a/rsocket-transport-tcp/src/codec.rs b/rsocket-transport-tcp/src/codec.rs deleted file mode 100644 index 606a629..0000000 --- a/rsocket-transport-tcp/src/codec.rs +++ /dev/null @@ -1,40 +0,0 @@ -use bytes::{Buf, BytesMut}; -use rsocket_rust::frame::Frame; -use rsocket_rust::utils::{u24, Writeable}; -use std::io::{Error, ErrorKind}; -use tokio_util::codec::{Decoder, Encoder}; - -pub struct LengthBasedFrameCodec; - -impl Decoder for LengthBasedFrameCodec { - type Item = Frame; - type Error = Error; - - fn decode(&mut self, buf: &mut BytesMut) -> Result, Self::Error> { - let actual = buf.len(); - if actual < 3 { - return Ok(None); - } - let l = u24::read(buf).into(); - if actual < 3 + l { - return Ok(None); - } - buf.advance(3); - let mut bb = buf.split_to(l); - match Frame::decode(&mut bb) { - Ok(v) => Ok(Some(v)), - Err(_e) => Err(Error::from(ErrorKind::InvalidInput)), - } - } -} - -impl Encoder for LengthBasedFrameCodec { - type Error = Error; - fn encode(&mut self, item: Frame, buf: &mut BytesMut) -> Result<(), Self::Error> { - let l = item.len(); - buf.reserve(3 + l); - u24::from(l).write_to(buf); - item.write_to(buf); - Ok(()) - } -} diff --git a/rsocket-transport-unix/src/codec.rs b/rsocket-transport-tcp/src/connection/codec.rs similarity index 85% rename from rsocket-transport-unix/src/codec.rs rename to rsocket-transport-tcp/src/connection/codec.rs index 606a629..99abce2 100644 --- a/rsocket-transport-unix/src/codec.rs +++ b/rsocket-transport-tcp/src/connection/codec.rs @@ -6,20 +6,22 @@ use tokio_util::codec::{Decoder, Encoder}; pub struct LengthBasedFrameCodec; +const LEN_BYTES: usize = 3; + impl Decoder for LengthBasedFrameCodec { type Item = Frame; type Error = Error; fn decode(&mut self, buf: &mut BytesMut) -> Result, Self::Error> { let actual = buf.len(); - if actual < 3 { + if actual < LEN_BYTES { return Ok(None); } let l = u24::read(buf).into(); - if actual < 3 + l { + if actual < LEN_BYTES + l { return Ok(None); } - buf.advance(3); + buf.advance(LEN_BYTES); let mut bb = buf.split_to(l); match Frame::decode(&mut bb) { Ok(v) => Ok(Some(v)), @@ -32,7 +34,7 @@ impl Encoder for LengthBasedFrameCodec { type Error = Error; fn encode(&mut self, item: Frame, buf: &mut BytesMut) -> Result<(), Self::Error> { let l = item.len(); - buf.reserve(3 + l); + buf.reserve(LEN_BYTES + l); u24::from(l).write_to(buf); item.write_to(buf); Ok(()) diff --git a/rsocket-transport-tcp/src/connection/mod.rs b/rsocket-transport-tcp/src/connection/mod.rs new file mode 100644 index 0000000..de8846d --- /dev/null +++ b/rsocket-transport-tcp/src/connection/mod.rs @@ -0,0 +1,6 @@ +mod codec; +mod tcp; +mod uds; + +pub use tcp::TcpConnection; +pub use uds::UnixConnection; diff --git a/rsocket-transport-tcp/src/connection/tcp.rs b/rsocket-transport-tcp/src/connection/tcp.rs new file mode 100644 index 0000000..9d2f81e --- /dev/null +++ b/rsocket-transport-tcp/src/connection/tcp.rs @@ -0,0 +1,64 @@ +use super::codec::LengthBasedFrameCodec; +use async_trait::async_trait; +use futures::stream::{SplitSink, SplitStream}; +use futures::{SinkExt, StreamExt}; +use rsocket_rust::frame::Frame; +use rsocket_rust::transport::{Connection, Reader, Writer}; +use rsocket_rust::Result; +use tokio::net::TcpStream; +use tokio_util::codec::Framed; + +#[derive(Debug)] +pub struct TcpConnection { + stream: TcpStream, +} + +struct InnerWriter { + sink: SplitSink, Frame>, +} + +struct InnerReader { + stream: SplitStream>, +} + +#[async_trait] +impl Writer for InnerWriter { + async fn write(&mut self, frame: Frame) -> Result<()> { + match self.sink.send(frame).await { + Ok(()) => Ok(()), + Err(e) => Err(Box::new(e)), + } + } +} + +#[async_trait] +impl Reader for InnerReader { + async fn read(&mut self) -> Option> { + match self.stream.next().await { + Some(Ok(frame)) => Some(Ok(frame)), + Some(Err(e)) => Some(Err(Box::new(e))), + None => None, + } + } +} + +impl Connection for TcpConnection { + fn split( + self, + ) -> ( + Box, + Box, + ) { + let (sink, stream) = Framed::new(self.stream, LengthBasedFrameCodec).split(); + ( + Box::new(InnerWriter { sink }), + Box::new(InnerReader { stream }), + ) + } +} + +impl From for TcpConnection { + fn from(stream: TcpStream) -> TcpConnection { + TcpConnection { stream } + } +} diff --git a/rsocket-transport-tcp/src/connection/uds.rs b/rsocket-transport-tcp/src/connection/uds.rs new file mode 100644 index 0000000..db14804 --- /dev/null +++ b/rsocket-transport-tcp/src/connection/uds.rs @@ -0,0 +1,64 @@ +use super::codec::LengthBasedFrameCodec; +use async_trait::async_trait; +use futures::stream::{SplitSink, SplitStream}; +use futures::{SinkExt, StreamExt}; +use rsocket_rust::frame::Frame; +use rsocket_rust::transport::{Connection, Reader, Writer}; +use rsocket_rust::Result; +use tokio::net::UnixStream; +use tokio_util::codec::Framed; + +#[derive(Debug)] +pub struct UnixConnection { + stream: UnixStream, +} + +struct InnerWriter { + sink: SplitSink, Frame>, +} + +struct InnerReader { + stream: SplitStream>, +} + +impl Connection for UnixConnection { + fn split( + self, + ) -> ( + Box, + Box, + ) { + let (sink, stream) = Framed::new(self.stream, LengthBasedFrameCodec).split(); + ( + Box::new(InnerWriter { sink }), + Box::new(InnerReader { stream }), + ) + } +} + +#[async_trait] +impl Writer for InnerWriter { + async fn write(&mut self, frame: Frame) -> Result<()> { + match self.sink.send(frame).await { + Ok(()) => Ok(()), + Err(e) => Err(Box::new(e)), + } + } +} + +#[async_trait] +impl Reader for InnerReader { + async fn read(&mut self) -> Option> { + match self.stream.next().await { + Some(Ok(frame)) => Some(Ok(frame)), + Some(Err(e)) => Some(Err(Box::new(e))), + None => None, + } + } +} + +impl From for UnixConnection { + fn from(stream: UnixStream) -> UnixConnection { + UnixConnection { stream } + } +} diff --git a/rsocket-transport-tcp/src/lib.rs b/rsocket-transport-tcp/src/lib.rs index df873d4..ab1a824 100644 --- a/rsocket-transport-tcp/src/lib.rs +++ b/rsocket-transport-tcp/src/lib.rs @@ -4,8 +4,10 @@ extern crate log; mod client; -mod codec; +mod connection; +mod misc; mod server; -pub use client::TcpClientTransport; -pub use server::TcpServerTransport; +pub use client::{TcpClientTransport, UnixClientTransport}; +pub use connection::{TcpConnection, UnixConnection}; +pub use server::{TcpServerTransport, UnixServerTransport}; diff --git a/rsocket-transport-tcp/src/misc.rs b/rsocket-transport-tcp/src/misc.rs new file mode 100644 index 0000000..218911c --- /dev/null +++ b/rsocket-transport-tcp/src/misc.rs @@ -0,0 +1,17 @@ +pub(crate) fn parse_uds_addr(addr: impl AsRef) -> String { + let addr = addr.as_ref(); + if addr.starts_with("unix://") || addr.starts_with("UNIX://") { + addr.chars().skip(7).collect::() + } else { + addr.to_owned() + } +} + +pub(crate) fn parse_tcp_addr(addr: impl AsRef) -> String { + let addr = addr.as_ref(); + if addr.starts_with("tcp://") || addr.starts_with("TCP://") { + addr.chars().skip(6).collect::() + } else { + addr.to_owned() + } +} diff --git a/rsocket-transport-tcp/src/server.rs b/rsocket-transport-tcp/src/server.rs deleted file mode 100644 index 936e285..0000000 --- a/rsocket-transport-tcp/src/server.rs +++ /dev/null @@ -1,65 +0,0 @@ -use super::client::TcpClientTransport; -use rsocket_rust::transport::{ClientTransport, ServerTransport}; -use std::error::Error; -use std::future::Future; -use std::net::SocketAddr; -use std::pin::Pin; -use tokio::net::TcpListener; - -pub struct TcpServerTransport { - addr: SocketAddr, -} - -impl TcpServerTransport { - fn new(addr: SocketAddr) -> TcpServerTransport { - TcpServerTransport { addr } - } -} - -impl ServerTransport for TcpServerTransport { - type Item = TcpClientTransport; - - fn start( - self, - starter: Option>, - acceptor: impl Fn(Self::Item) + Send + Sync + 'static, - ) -> Pin>>>> - where - Self::Item: ClientTransport + Sized, - { - Box::pin(async move { - match TcpListener::bind(&self.addr).await { - Ok(mut listener) => { - debug!("listening on: {}", &self.addr); - if let Some(mut bingo) = starter { - bingo(); - } - while let Ok((socket, _)) = listener.accept().await { - let tp = TcpClientTransport::from(socket); - acceptor(tp); - } - Ok(()) - } - Err(e) => Err(e.into_inner().unwrap()), - } - }) - } -} - -impl From for TcpServerTransport { - fn from(addr: SocketAddr) -> TcpServerTransport { - TcpServerTransport::new(addr) - } -} - -impl From for TcpServerTransport { - fn from(addr: String) -> TcpServerTransport { - TcpServerTransport::new(addr.parse().unwrap()) - } -} - -impl From<&str> for TcpServerTransport { - fn from(addr: &str) -> TcpServerTransport { - TcpServerTransport::new(addr.parse().unwrap()) - } -} diff --git a/rsocket-transport-tcp/src/server/mod.rs b/rsocket-transport-tcp/src/server/mod.rs new file mode 100644 index 0000000..2adea25 --- /dev/null +++ b/rsocket-transport-tcp/src/server/mod.rs @@ -0,0 +1,5 @@ +mod tcp; +mod uds; + +pub use tcp::TcpServerTransport; +pub use uds::UnixServerTransport; diff --git a/rsocket-transport-tcp/src/server/tcp.rs b/rsocket-transport-tcp/src/server/tcp.rs new file mode 100644 index 0000000..562ed5e --- /dev/null +++ b/rsocket-transport-tcp/src/server/tcp.rs @@ -0,0 +1,70 @@ +use crate::{client::TcpClientTransport, misc::parse_tcp_addr}; +use async_trait::async_trait; +use rsocket_rust::{transport::ServerTransport, Result}; +use std::net::SocketAddr; +use tokio::net::TcpListener; + +#[derive(Debug)] +pub struct TcpServerTransport { + addr: SocketAddr, + listener: Option, +} + +impl TcpServerTransport { + fn new(addr: SocketAddr) -> TcpServerTransport { + TcpServerTransport { + addr, + listener: None, + } + } +} + +#[async_trait] +impl ServerTransport for TcpServerTransport { + type Item = TcpClientTransport; + + async fn start(&mut self) -> Result<()> { + if self.listener.is_some() { + return Ok(()); + } + match TcpListener::bind(self.addr).await { + Ok(listener) => { + self.listener = Some(listener); + debug!("listening on: {}", &self.addr); + Ok(()) + } + Err(e) => Err(Box::new(e)), + } + } + + async fn next(&mut self) -> Option> { + match self.listener.as_mut() { + Some(listener) => match listener.accept().await { + Ok((socket, _)) => { + let tp = TcpClientTransport::from(socket); + Some(Ok(tp)) + } + Err(e) => Some(Err(Box::new(e))), + }, + None => Some(Err("err".into())), + } + } +} + +impl From for TcpServerTransport { + fn from(addr: SocketAddr) -> TcpServerTransport { + TcpServerTransport::new(addr) + } +} + +impl From for TcpServerTransport { + fn from(addr: String) -> TcpServerTransport { + TcpServerTransport::new(parse_tcp_addr(addr).parse().unwrap()) + } +} + +impl From<&str> for TcpServerTransport { + fn from(addr: &str) -> TcpServerTransport { + TcpServerTransport::new(parse_tcp_addr(addr).parse().unwrap()) + } +} diff --git a/rsocket-transport-tcp/src/server/uds.rs b/rsocket-transport-tcp/src/server/uds.rs new file mode 100644 index 0000000..b509a53 --- /dev/null +++ b/rsocket-transport-tcp/src/server/uds.rs @@ -0,0 +1,69 @@ +use crate::client::UnixClientTransport; +use crate::misc::parse_uds_addr; +use async_trait::async_trait; +use rsocket_rust::{transport::ServerTransport, Result}; +use tokio::net::UnixListener; + +#[derive(Debug)] +pub struct UnixServerTransport { + addr: String, + listener: Option, +} + +impl UnixServerTransport { + fn new(addr: String) -> UnixServerTransport { + UnixServerTransport { + addr, + listener: None, + } + } +} + +#[async_trait] +impl ServerTransport for UnixServerTransport { + type Item = UnixClientTransport; + + async fn start(&mut self) -> Result<()> { + if self.listener.is_some() { + return Ok(()); + } + match UnixListener::bind(&self.addr) { + Ok(listener) => { + self.listener = Some(listener); + debug!("listening on: {}", &self.addr); + Ok(()) + } + Err(e) => Err(Box::new(e)), + } + } + + async fn next(&mut self) -> Option> { + match self.listener.as_mut() { + Some(listener) => match listener.accept().await { + Ok((socket, _)) => Some(Ok(UnixClientTransport::from(socket))), + Err(e) => Some(Err(Box::new(e))), + }, + None => None, + } + } +} + +impl Drop for UnixServerTransport { + fn drop(&mut self) { + if let Err(e) = std::fs::remove_file(&self.addr) { + warn!("remove unix sock file failed: {}", e); + } + } +} + +impl From for UnixServerTransport { + fn from(addr: String) -> UnixServerTransport { + UnixServerTransport::new(parse_uds_addr(addr)) + } +} + +impl From<&str> for UnixServerTransport { + fn from(addr: &str) -> UnixServerTransport { + UnixServerTransport::new(parse_uds_addr(addr)) + } +} diff --git a/rsocket-transport-unix/Cargo.toml b/rsocket-transport-unix/Cargo.toml deleted file mode 100644 index f4e5d2a..0000000 --- a/rsocket-transport-unix/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -name = "rsocket_rust_transport_unix" -version = "0.5.3" -authors = ["seal <578935869@qq.com>"] -edition = "2018" -license = "Apache-2.0" -readme = "README.md" -repository = "https://github.com/rsocket/rsocket-rust" -homepage = "https://github.com/rsocket/rsocket-rust" -description = "Unix Domain Socket RSocket transport implementation." - -[dependencies] -log = "0.4.8" -futures = "0.3.5" -bytes = "0.5.4" - -[dependencies.rsocket_rust] -version = "0.5.3" -features = ["frame"] - -[dependencies.tokio] -version = "0.2.21" -default-features = false -features = [ "rt-core", "rt-threaded", "uds", "sync", "stream" ] - -[dependencies.tokio-util] -version = "0.3.1" -default-features = false -features = ["codec"] \ No newline at end of file diff --git a/rsocket-transport-unix/README.md b/rsocket-transport-unix/README.md deleted file mode 100644 index a9d281d..0000000 --- a/rsocket-transport-unix/README.md +++ /dev/null @@ -1,85 +0,0 @@ -# RSocket Transport For Unix Domain Socket - -## Example - -Add dependencies in your `Cargo.toml`. - -```toml -[dependencies] -tokio = "0.2.21" -rsocket_rust = "0.5.3" -rsocket_rust_transport_unix = "0.5.3" -``` - -### Server - -```rust -use log::info; -use rsocket_rust::prelude::{EchoRSocket, RSocketFactory, ServerResponder}; -use rsocket_rust_transport_unix::UnixServerTransport; -use std::error::Error; - -#[tokio::main] -async fn main() -> Result<(), Box> { - - let transport: UnixServerTransport = UnixServerTransport::from("/tmp/rsocket-uds.sock"); - - let responder: ServerResponder = Box::new(|setup, _socket| { - info!("accept setup: {:?}", setup); - Ok(Box::new(EchoRSocket)) - // Or you can reject setup - // Err(From::from("SETUP_NOT_ALLOW")) - }); - - let on_start: Box = - Box::new(|| info!("+++++++ echo server started! +++++++")); - - RSocketFactory::receive() - .transport(transport) - .acceptor(responder) - .on_start(on_start) - .serve() - .await?; - - Ok(()) -} - -``` - -### Client - -```rust -use log::info; -use rsocket_rust::prelude::{ClientResponder, EchoRSocket, Payload, RSocket, RSocketFactory}; -use rsocket_rust_transport_unix::UnixClientTransport; -use std::error::Error; - -#[tokio::main] -async fn main() -> Result<(), Box> { - - let responder: ClientResponder = Box::new(|| Box::new(EchoRSocket)); - - let client = RSocketFactory::connect() - .acceptor(responder) - .transport(UnixClientTransport::from("/tmp/rsocket-uds.sock")) - .setup(Payload::from("READY!")) - .mime_type("text/plain", "text/plain") - .start() - .await - .unwrap(); - - let request_payload: Payload = Payload::builder() - .set_data_utf8("Hello World!") - .set_metadata_utf8("Rust") - .build(); - - let res = client.request_response(request_payload).await.unwrap(); - - info!("got: {:?}", res); - - client.close(); - - Ok(()) -} - -``` diff --git a/rsocket-transport-unix/src/client.rs b/rsocket-transport-unix/src/client.rs deleted file mode 100644 index 087345a..0000000 --- a/rsocket-transport-unix/src/client.rs +++ /dev/null @@ -1,113 +0,0 @@ -use super::codec::LengthBasedFrameCodec; -use futures::{SinkExt, StreamExt}; -use rsocket_rust::error::RSocketError; -use rsocket_rust::frame::Frame; -use rsocket_rust::runtime::{DefaultSpawner, Spawner}; -use rsocket_rust::transport::{ClientTransport, Rx, Tx, TxOnce}; -use std::io; -use std::os::unix::net::UnixStream as StdUnixStream; -use std::str::FromStr; -use tokio::net::UnixStream; -use tokio_util::codec::Framed; - -enum Connector { - Direct(UnixStream), - Lazy(String), -} - -pub struct UnixClientTransport { - connector: Connector, -} - -impl UnixClientTransport { - #[inline] - fn new(connector: Connector) -> UnixClientTransport { - UnixClientTransport { connector } - } - - #[inline] - async fn connect(self) -> Result { - match self.connector { - Connector::Direct(stream) => Ok(stream), - Connector::Lazy(addr) => match StdUnixStream::connect(&addr) { - Ok(raw) => match UnixStream::from_std(raw) { - Ok(stream) => Ok(stream), - Err(e) => Err(RSocketError::from(e)), - }, - Err(e) => Err(RSocketError::from(e)), - }, - } - } -} - -impl ClientTransport for UnixClientTransport { - fn attach( - self, - incoming: Tx, - mut sending: Rx, - connected: Option>>, - ) { - DefaultSpawner.spawn(async move { - match self.connect().await { - Ok(socket) => { - if let Some(sender) = connected { - sender.send(Ok(())).unwrap(); - } - let (mut writer, mut reader) = - Framed::new(socket, LengthBasedFrameCodec).split(); - DefaultSpawner.spawn(async move { - while let Some(it) = reader.next().await { - incoming.unbounded_send(it.unwrap()).unwrap(); - } - }); - // loop write - while let Some(it) = sending.next().await { - debug!("===> SND: {:?}", &it); - writer.send(it).await.unwrap() - } - } - Err(e) => { - if let Some(sender) = connected { - sender.send(Err(e)).unwrap(); - } - } - } - }); - } -} - -impl FromStr for UnixClientTransport { - type Err = io::Error; - - fn from_str(addr: &str) -> Result { - let socket_addr = if addr.starts_with("unix://") || addr.starts_with("UNIX://") { - addr.chars().skip(7).collect::() - } else { - addr.to_string() - }; - Ok(UnixClientTransport::new(Connector::Lazy(socket_addr))) - } -} - -impl From for UnixClientTransport { - fn from(addr: String) -> UnixClientTransport { - UnixClientTransport::new(Connector::Lazy(addr)) - } -} - -impl From<&str> for UnixClientTransport { - fn from(addr: &str) -> UnixClientTransport { - let socket_addr: String = if addr.starts_with("unix://") || addr.starts_with("UNIX://") { - addr.chars().skip(7).collect::() - } else { - addr.to_string() - }; - UnixClientTransport::new(Connector::Lazy(socket_addr)) - } -} - -impl From for UnixClientTransport { - fn from(socket: UnixStream) -> UnixClientTransport { - UnixClientTransport::new(Connector::Direct(socket)) - } -} diff --git a/rsocket-transport-unix/src/lib.rs b/rsocket-transport-unix/src/lib.rs deleted file mode 100644 index 7ec5d51..0000000 --- a/rsocket-transport-unix/src/lib.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![allow(clippy::type_complexity)] - -#[macro_use] -extern crate log; - -mod client; -mod codec; -mod server; - -pub use client::UnixClientTransport; -pub use server::UnixServerTransport; diff --git a/rsocket-transport-unix/src/server.rs b/rsocket-transport-unix/src/server.rs deleted file mode 100644 index 45695b2..0000000 --- a/rsocket-transport-unix/src/server.rs +++ /dev/null @@ -1,65 +0,0 @@ -use super::client::UnixClientTransport; -use rsocket_rust::transport::{ClientTransport, ServerTransport}; -use std::error::Error; -use std::future::Future; -use std::pin::Pin; -use tokio::net::UnixListener; - -pub struct UnixServerTransport { - addr: String, -} - -impl UnixServerTransport { - fn new(addr: String) -> UnixServerTransport { - UnixServerTransport { addr } - } -} - -impl ServerTransport for UnixServerTransport { - type Item = UnixClientTransport; - - fn start( - self, - starter: Option>, - acceptor: impl Fn(Self::Item) + Send + Sync + 'static, - ) -> Pin>>>> - where - Self::Item: ClientTransport + Sized, - { - Box::pin(async move { - match UnixListener::bind(&self.addr.as_str()) { - Ok(mut listener) => { - debug!("listening on: {}", &self.addr); - if let Some(mut bingo) = starter { - bingo(); - } - while let Ok((socket, _)) = listener.accept().await { - let tp = UnixClientTransport::from(socket); - acceptor(tp); - } - - Ok(()) - } - Err(e) => Err(e.into_inner().unwrap()), - } - }) - } -} - -impl Drop for UnixServerTransport { - fn drop(&mut self) { - std::fs::remove_file(&self.addr.as_str()).unwrap(); - } -} - -impl From for UnixServerTransport { - fn from(addr: String) -> UnixServerTransport { - UnixServerTransport::new(addr.parse().unwrap()) - } -} - -impl From<&str> for UnixServerTransport { - fn from(addr: &str) -> UnixServerTransport { - UnixServerTransport::new(addr.parse().unwrap()) - } -} diff --git a/rsocket-transport-wasm/Cargo.toml b/rsocket-transport-wasm/Cargo.toml index 56b7b48..52c7703 100644 --- a/rsocket-transport-wasm/Cargo.toml +++ b/rsocket-transport-wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_wasm" -version = "0.5.3" +version = "0.6.0" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" @@ -10,24 +10,25 @@ homepage = "https://github.com/rsocket/rsocket-rust" description = "WASM Websocket RSocket transport implementation." [dependencies] -bytes = "0.5.4" -wasm-bindgen-futures = "0.4.13" +bytes = "0.5.6" +wasm-bindgen-futures = "0.4.18" futures-channel = "0.3.5" futures-util = "0.3.5" -js-sys = "0.3.40" -serde = "1.0.111" -serde_derive = "1.0.111" +js-sys = "0.3.45" +serde = "1.0.116" +serde_derive = "1.0.116" +async-trait = "0.1.40" [dependencies.rsocket_rust] -version = "0.5.3" +path = "../rsocket" features = ["frame"] [dependencies.wasm-bindgen] -version = "0.2.63" +version = "0.2.68" features = ["serde-serialize"] [dependencies.web-sys] -version = "0.3.40" +version = "0.3.45" features = [ "FileReader", "ProgressEvent", diff --git a/rsocket-transport-wasm/src/client.rs b/rsocket-transport-wasm/src/client.rs index 4ea6e31..f2e2a10 100644 --- a/rsocket-transport-wasm/src/client.rs +++ b/rsocket-transport-wasm/src/client.rs @@ -1,17 +1,19 @@ +use super::connection::WebsocketConnection; +use async_trait::async_trait; use bytes::BytesMut; -use futures_channel::oneshot; +use futures_channel::{mpsc, oneshot}; use futures_util::StreamExt; use js_sys::{ArrayBuffer, Uint8Array}; -use rsocket_rust::error::RSocketError; use rsocket_rust::frame::Frame; -use rsocket_rust::transport::{ClientTransport, Rx, Tx, TxOnce}; +use rsocket_rust::transport::Transport; use rsocket_rust::utils::Writeable; +use rsocket_rust::Result; use std::cell::RefCell; use std::future::Future; use std::rc::Rc; use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; -use wasm_bindgen_futures::spawn_local; +use wasm_bindgen_futures; use web_sys::{ErrorEvent, Event, FileReader, MessageEvent, ProgressEvent, WebSocket}; macro_rules! console_log { @@ -45,22 +47,57 @@ impl WebsocketClientTransport { drop(on_open); } } + + #[inline] + fn read_binary(value: JsValue, mut incoming: mpsc::Sender) { + let reader = FileReader::new().unwrap_throw(); + let state = Rc::new(RefCell::new(None)); + let onload = { + let state = state.clone(); + let reader = reader.clone(); + Closure::once(move |_: ProgressEvent| { + *state.borrow_mut() = None; + let data: ArrayBuffer = reader.result().unwrap_throw().unchecked_into(); + let raw: Vec = Uint8Array::new(&data).to_vec(); + // Use data... + let mut bf = BytesMut::from(&raw[..]); + let msg = Frame::decode(&mut bf).unwrap(); + incoming.try_send(msg).unwrap(); + }) + }; + let onerror = { + let state = state.clone(); + Closure::once(move |_: ErrorEvent| { + *state.borrow_mut() = None; + // let err = e.error(); + // let error = reader.error().unwrap_throw(); + // TODO: Handle error... + }) + }; + reader.set_onload(Some(onload.as_ref().unchecked_ref())); + reader.set_onerror(Some(onerror.as_ref().unchecked_ref())); + *state.borrow_mut() = Some((onload, onerror)); + reader + .read_as_array_buffer(value.as_ref().unchecked_ref()) + .unwrap_throw(); + } } -impl ClientTransport for WebsocketClientTransport { - fn attach( - self, - incoming: Tx, - mut sending: Rx, - connected: Option>>, - ) { - spawn_local(async move { +#[async_trait] +impl Transport for WebsocketClientTransport { + type Conn = WebsocketConnection; + + async fn connect(self) -> Result { + let (rcv_tx, rcv_rx) = mpsc::channel::(32); + let (snd_tx, mut snd_rx) = mpsc::channel::(32); + let (connected, connected_rx) = oneshot::channel::>(); + wasm_bindgen_futures::spawn_local(async move { match WebSocket::new(&self.url) { Ok(ws) => { // on message let on_message = Closure::wrap(Box::new(move |e: MessageEvent| { let data: JsValue = e.data(); - read_binary(data, incoming.clone()); + Self::read_binary(data, rcv_tx.clone()); }) as Box); ws.set_onmessage(Some(on_message.as_ref().unchecked_ref())); @@ -83,11 +120,9 @@ impl ClientTransport for WebsocketClientTransport { Self::wait_for_open(&ws).await; - if let Some(sender) = connected { - sender.send(Ok(())).unwrap(); - } + connected.send(Ok(())).unwrap(); - while let Some(v) = sending.next().await { + while let Some(v) = snd_rx.next().await { let mut bf = BytesMut::new(); v.write_to(&mut bf); let raw = bf.to_vec(); @@ -97,14 +132,14 @@ impl ClientTransport for WebsocketClientTransport { console_log!("***** attch end *****"); } Err(e) => { - if let Some(sender) = connected { - sender - .send(Err(RSocketError::from(e.as_string().unwrap()))) - .unwrap(); - } + connected.send(Err(e.as_string().unwrap().into())).unwrap(); } } }); + match connected_rx.await.expect("connected channel closed") { + Ok(_) => Ok(WebsocketConnection::new(snd_tx, rcv_rx)), + Err(e) => Err(e), + } } } @@ -116,44 +151,3 @@ where WebsocketClientTransport { url: url.into() } } } - -#[inline] -fn read_binary(value: JsValue, incoming: Tx) { - let reader = FileReader::new().unwrap_throw(); - - let state = Rc::new(RefCell::new(None)); - - let onload = { - let state = state.clone(); - let reader = reader.clone(); - - Closure::once(move |_: ProgressEvent| { - *state.borrow_mut() = None; - let data: ArrayBuffer = reader.result().unwrap_throw().unchecked_into(); - let raw: Vec = Uint8Array::new(&data).to_vec(); - // Use data... - let mut bf = BytesMut::from(&raw[..]); - let msg = Frame::decode(&mut bf).unwrap(); - incoming.unbounded_send(msg).unwrap(); - }) - }; - - let onerror = { - let state = state.clone(); - Closure::once(move |_: ErrorEvent| { - *state.borrow_mut() = None; - // let err = e.error(); - // let error = reader.error().unwrap_throw(); - // TODO: Handle error... - }) - }; - - reader.set_onload(Some(onload.as_ref().unchecked_ref())); - reader.set_onerror(Some(onerror.as_ref().unchecked_ref())); - - *state.borrow_mut() = Some((onload, onerror)); - - reader - .read_as_array_buffer(value.as_ref().unchecked_ref()) - .unwrap_throw(); -} diff --git a/rsocket-transport-wasm/src/connection.rs b/rsocket-transport-wasm/src/connection.rs new file mode 100644 index 0000000..9a54739 --- /dev/null +++ b/rsocket-transport-wasm/src/connection.rs @@ -0,0 +1,59 @@ +use async_trait::async_trait; +use futures_channel::mpsc; +use futures_util::{SinkExt, StreamExt}; +use rsocket_rust::transport::{Connection, Reader, Writer}; +use rsocket_rust::{frame::Frame, Result}; + +#[derive(Debug)] +pub struct WebsocketConnection { + rx: mpsc::Receiver, + tx: mpsc::Sender, +} + +struct InnerWriter { + tx: mpsc::Sender, +} + +struct InnerReader { + rx: mpsc::Receiver, +} + +impl WebsocketConnection { + pub(crate) fn new(tx: mpsc::Sender, rx: mpsc::Receiver) -> WebsocketConnection { + WebsocketConnection { rx, tx } + } +} + +#[async_trait] +impl Writer for InnerWriter { + async fn write(&mut self, frame: Frame) -> Result<()> { + match self.tx.send(frame).await { + Ok(()) => Ok(()), + Err(e) => Err(Box::new(e)), + } + } +} + +#[async_trait] +impl Reader for InnerReader { + async fn read(&mut self) -> Option> { + match self.rx.next().await { + Some(frame) => Some(Ok(frame)), + None => None, + } + } +} + +impl Connection for WebsocketConnection { + fn split( + self, + ) -> ( + Box, + Box, + ) { + ( + Box::new(InnerWriter { tx: self.tx }), + Box::new(InnerReader { rx: self.rx }), + ) + } +} diff --git a/rsocket-transport-wasm/src/lib.rs b/rsocket-transport-wasm/src/lib.rs index c7ac55f..cab558a 100644 --- a/rsocket-transport-wasm/src/lib.rs +++ b/rsocket-transport-wasm/src/lib.rs @@ -4,9 +4,9 @@ extern crate serde_derive; mod client; +mod connection; mod misc; -mod runtime; pub use client::WebsocketClientTransport; +pub use connection::WebsocketConnection; pub use misc::{connect, new_payload, JsClient, JsPayload}; -pub use runtime::WASMSpawner; diff --git a/rsocket-transport-wasm/src/misc.rs b/rsocket-transport-wasm/src/misc.rs index 38fbfda..4682622 100644 --- a/rsocket-transport-wasm/src/misc.rs +++ b/rsocket-transport-wasm/src/misc.rs @@ -1,7 +1,7 @@ use super::client::WebsocketClientTransport; -use super::runtime::WASMSpawner; use js_sys::{Promise, Uint8Array}; use rsocket_rust::prelude::*; +use rsocket_rust::Client; use wasm_bindgen::prelude::{wasm_bindgen, JsValue}; use wasm_bindgen_futures::future_to_promise; @@ -13,7 +13,7 @@ pub struct JsPayload { #[wasm_bindgen] pub struct JsClient { - inner: Client, + inner: Client, } impl Into for &JsPayload { @@ -58,7 +58,7 @@ pub fn new_payload(data: JsValue, metadata: JsValue) -> JsValue { pub async fn connect(url: String) -> Result { match RSocketFactory::connect() .transport(WebsocketClientTransport::from(url)) - .start_with_runtime(WASMSpawner) + .start() .await { Ok(inner) => Ok(JsClient { inner }), diff --git a/rsocket-transport-wasm/src/runtime.rs b/rsocket-transport-wasm/src/runtime.rs deleted file mode 100644 index 4b39ae6..0000000 --- a/rsocket-transport-wasm/src/runtime.rs +++ /dev/null @@ -1,15 +0,0 @@ -use rsocket_rust::runtime::Spawner; -use std::future::Future; -use wasm_bindgen_futures::spawn_local; - -#[derive(Clone, Copy, Debug)] -pub struct WASMSpawner; - -impl Spawner for WASMSpawner { - fn spawn(&self, task: F) - where - F: Send + Future + 'static, - { - spawn_local(task); - } -} diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index 79cbb4f..225c9e5 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_websocket" -version = "0.5.3" +version = "0.6.0" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" @@ -10,17 +10,18 @@ homepage = "https://github.com/rsocket/rsocket-rust" description = "Websocket RSocket transport implementation." [dependencies] -log = "0.4.8" +log = "0.4.11" futures = "0.3.5" -bytes = "0.5.4" +bytes = "0.5.6" url = "2.1.1" -tokio-tungstenite = "0.10.1" +tokio-tungstenite = "0.11.0" +async-trait = "0.1.40" [dependencies.rsocket_rust] -version = "0.5.3" +path = "../rsocket" features = ["frame"] [dependencies.tokio] -version = "0.2.21" +version = "0.2.22" default-features = false features = [ "rt-core", "rt-threaded", "tcp", "sync", "stream" ] diff --git a/rsocket-transport-websocket/src/client.rs b/rsocket-transport-websocket/src/client.rs index e4bbbce..42fced4 100644 --- a/rsocket-transport-websocket/src/client.rs +++ b/rsocket-transport-websocket/src/client.rs @@ -1,89 +1,46 @@ -use bytes::{BufMut, BytesMut}; -use futures::{SinkExt, StreamExt}; -use rsocket_rust::error::RSocketError; -use rsocket_rust::frame::Frame; -use rsocket_rust::runtime::{DefaultSpawner, Spawner}; -use rsocket_rust::transport::{ClientTransport, Rx, Tx, TxOnce}; -use rsocket_rust::utils::Writeable; +use super::connection::WebsocketConnection; +use async_trait::async_trait; +use rsocket_rust::{transport::Transport, Result}; use std::net::SocketAddr; use tokio::net::TcpStream; -use tokio_tungstenite::{accept_async, connect_async, tungstenite::Message, WebSocketStream}; +use tokio_tungstenite::{accept_async, connect_async}; use url::Url; -enum Connector { +#[derive(Debug)] +pub(crate) enum Connector { Direct(TcpStream), Lazy(Url), } +#[derive(Debug)] pub struct WebsocketClientTransport { connector: Connector, } impl WebsocketClientTransport { - fn new(connector: Connector) -> WebsocketClientTransport { + pub(crate) fn new(connector: Connector) -> WebsocketClientTransport { WebsocketClientTransport { connector } } +} + +#[async_trait] +impl Transport for WebsocketClientTransport { + type Conn = WebsocketConnection; - async fn connect(self) -> Result, RSocketError> { + async fn connect(self) -> Result { match self.connector { Connector::Direct(stream) => match accept_async(stream).await { - Ok(ws) => Ok(ws), - Err(e) => Err(RSocketError::from(format!("{}", e))), + Ok(ws) => Ok(WebsocketConnection::new(ws)), + Err(e) => Err(Box::new(e)), }, Connector::Lazy(u) => match connect_async(u).await { - Ok((stream, _)) => Ok(stream), - Err(e) => Err(RSocketError::from(format!("{}", e))), + Ok((stream, _)) => Ok(WebsocketConnection::new(stream)), + Err(e) => Err(Box::new(e)), }, } } } -impl ClientTransport for WebsocketClientTransport { - fn attach( - self, - incoming: Tx, - mut sending: Rx, - connected: Option>>, - ) { - DefaultSpawner.spawn(async move { - match self.connect().await { - Ok(ws_stream) => { - if let Some(sender) = connected { - sender.send(Ok(())).unwrap(); - } - let (mut write, mut read) = ws_stream.split(); - DefaultSpawner.spawn(async move { - while let Some(next) = read.next().await { - match next { - Ok(msg) => { - let raw = msg.into_data(); - let mut bf = BytesMut::new(); - bf.put_slice(&raw[..]); - let f = Frame::decode(&mut bf).unwrap(); - incoming.unbounded_send(f).unwrap(); - } - Err(e) => error!("got error: {}", e), - } - } - }); - while let Some(it) = sending.next().await { - debug!("===> SND: {:?}", &it); - let mut bf = BytesMut::new(); - it.write_to(&mut bf); - let msg = Message::binary(bf.to_vec()); - write.send(msg).await.unwrap(); - } - } - Err(e) => { - if let Some(sender) = connected { - sender.send(Err(e)).unwrap(); - } - } - }; - }); - } -} - impl From for WebsocketClientTransport { fn from(socket: TcpStream) -> WebsocketClientTransport { WebsocketClientTransport::new(Connector::Direct(socket)) diff --git a/rsocket-transport-websocket/src/connection.rs b/rsocket-transport-websocket/src/connection.rs new file mode 100644 index 0000000..028bf74 --- /dev/null +++ b/rsocket-transport-websocket/src/connection.rs @@ -0,0 +1,78 @@ +use async_trait::async_trait; +use bytes::{BufMut, BytesMut}; +use futures::stream::{SplitSink, SplitStream}; +use futures::{SinkExt, StreamExt}; +use rsocket_rust::{ + frame::Frame, + transport::{Connection, Reader, Writer}, + utils::Writeable, + Result, +}; +use tokio::net::TcpStream; +use tokio_tungstenite::{tungstenite::Message, WebSocketStream}; + +#[derive(Debug)] +pub struct WebsocketConnection { + stream: WebSocketStream, +} + +struct InnerWriter { + sink: SplitSink, Message>, +} + +struct InnerReader { + stream: SplitStream>, +} + +impl WebsocketConnection { + pub(crate) fn new(stream: WebSocketStream) -> WebsocketConnection { + WebsocketConnection { stream } + } +} + +impl Connection for WebsocketConnection { + fn split( + self, + ) -> ( + Box, + Box, + ) { + let (sink, stream) = self.stream.split(); + ( + Box::new(InnerWriter { sink }), + Box::new(InnerReader { stream }), + ) + } +} + +#[async_trait] +impl Writer for InnerWriter { + async fn write(&mut self, frame: Frame) -> Result<()> { + let mut bf = BytesMut::new(); + frame.write_to(&mut bf); + let msg = Message::binary(bf.to_vec()); + match self.sink.send(msg).await { + Ok(()) => Ok(()), + Err(e) => Err(Box::new(e)), + } + } +} + +#[async_trait] +impl Reader for InnerReader { + async fn read(&mut self) -> Option> { + match self.stream.next().await { + Some(Ok(msg)) => { + let raw = msg.into_data(); + let mut bf = BytesMut::new(); + bf.put_slice(&raw[..]); + match Frame::decode(&mut bf) { + Ok(frame) => Some(Ok(frame)), + Err(e) => Some(Err(e)), + } + } + Some(Err(e)) => Some(Err(Box::new(e))), + None => None, + } + } +} diff --git a/rsocket-transport-websocket/src/lib.rs b/rsocket-transport-websocket/src/lib.rs index 551decb..6ad58fc 100644 --- a/rsocket-transport-websocket/src/lib.rs +++ b/rsocket-transport-websocket/src/lib.rs @@ -4,6 +4,7 @@ extern crate log; mod client; +mod connection; mod server; pub use client::WebsocketClientTransport; diff --git a/rsocket-transport-websocket/src/server.rs b/rsocket-transport-websocket/src/server.rs index 0fc9052..edec38a 100644 --- a/rsocket-transport-websocket/src/server.rs +++ b/rsocket-transport-websocket/src/server.rs @@ -1,57 +1,83 @@ use super::client::WebsocketClientTransport; -use rsocket_rust::transport::ServerTransport; -use std::error::Error; -use std::future::Future; +use async_trait::async_trait; +use rsocket_rust::{transport::ServerTransport, Result}; use std::net::SocketAddr; -use std::pin::Pin; use tokio::net::TcpListener; +const WS_PROTO: &str = "ws://"; + +#[derive(Debug)] pub struct WebsocketServerTransport { addr: SocketAddr, + listener: Option, +} + +#[async_trait] +impl ServerTransport for WebsocketServerTransport { + type Item = WebsocketClientTransport; + + async fn start(&mut self) -> Result<()> { + if self.listener.is_some() { + warn!("websocket server transport started already!"); + return Ok(()); + } + match TcpListener::bind(self.addr).await { + Ok(listener) => { + self.listener = Some(listener); + Ok(()) + } + Err(e) => Err(Box::new(e)), + } + } + + async fn next(&mut self) -> Option> { + match self.listener.as_mut() { + Some(listener) => match listener.accept().await { + Ok((socket, _)) => Some(Ok(WebsocketClientTransport::from(socket))), + Err(e) => Some(Err(Box::new(e))), + }, + None => None, + } + } +} + +#[inline] +fn parse_socket_addr(addr: impl AsRef) -> SocketAddr { + let addr = addr.as_ref(); + if addr.starts_with(WS_PROTO) { + addr.chars() + .skip(WS_PROTO.len()) + .collect::() + .parse() + } else { + addr.parse() + } + .expect("Invalid transport string!") } impl From for WebsocketServerTransport { fn from(addr: SocketAddr) -> WebsocketServerTransport { - WebsocketServerTransport { addr } + WebsocketServerTransport { + addr, + listener: None, + } } } impl From for WebsocketServerTransport { fn from(addr: String) -> WebsocketServerTransport { - let socket_addr = addr.parse().unwrap(); - WebsocketServerTransport { addr: socket_addr } + WebsocketServerTransport { + addr: parse_socket_addr(addr), + listener: None, + } } } impl From<&str> for WebsocketServerTransport { fn from(addr: &str) -> WebsocketServerTransport { - let socket_addr = addr.parse().unwrap(); - WebsocketServerTransport { addr: socket_addr } - } -} - -impl ServerTransport for WebsocketServerTransport { - type Item = WebsocketClientTransport; - - fn start( - self, - starter: Option>, - acceptor: impl Fn(WebsocketClientTransport) + Send + Sync + 'static, - ) -> Pin>>>> { - Box::pin(async move { - match TcpListener::bind(self.addr).await { - Ok(mut listener) => { - if let Some(mut bingo) = starter { - bingo(); - } - while let Ok((socket, _)) = listener.accept().await { - let tp = WebsocketClientTransport::from(socket); - acceptor(tp); - } - Ok(()) - } - Err(e) => Err(e.into_inner().unwrap()), - } - }) + WebsocketServerTransport { + addr: parse_socket_addr(addr), + listener: None, + } } } diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index 50479d4..77b92d3 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust" -version = "0.5.3" +version = "0.6.0" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" @@ -10,16 +10,22 @@ homepage = "https://github.com/rsocket/rsocket-rust" description = "rsocket-rust is an implementation of the RSocket protocol in Rust." [dependencies] -log = "0.4.8" -bytes = "0.5.4" +log = "0.4.11" +bytes = "0.5.6" futures = "0.3.5" lazy_static = "1.4.0" +async-trait = "0.1.40" +dashmap = "3.11.10" + +[target.'cfg(target_arch = "wasm32")'.dependencies] +wasm-bindgen-futures = "0.4.18" [dependencies.tokio] -version = "0.2.21" +version = "0.2.22" default-features = false features = [ "rt-core", "rt-threaded", "sync", "stream" ] [features] default = [] -frame = [] \ No newline at end of file +frame = [] +wasm = [] \ No newline at end of file diff --git a/rsocket/src/x/client.rs b/rsocket/src/core/client.rs similarity index 60% rename from rsocket/src/x/client.rs rename to rsocket/src/core/client.rs index 8f7a617..d100b06 100644 --- a/rsocket/src/x/client.rs +++ b/rsocket/src/core/client.rs @@ -1,31 +1,29 @@ use crate::error::RSocketError; use crate::frame::{self, Frame}; use crate::payload::{Payload, SetupPayload, SetupPayloadBuilder}; -use crate::runtime::{DefaultSpawner, Spawner}; +use crate::runtime; use crate::spi::{ClientResponder, Flux, Mono, RSocket}; use crate::transport::{ - self, Acceptor, ClientTransport, DuplexSocket, Rx, RxOnce, Splitter, Tx, TxOnce, + self, Acceptor, Connection, DuplexSocket, Reader, Splitter, Transport, Writer, }; -use futures::channel::{mpsc, oneshot}; -use futures::{Future, Stream}; +use crate::Result; +use futures::{future, FutureExt, SinkExt, StreamExt}; use std::error::Error; use std::net::SocketAddr; use std::pin::Pin; -use std::result::Result; use std::sync::Arc; use std::time::Duration; +use tokio::sync::{mpsc, Mutex, Notify}; #[derive(Clone)] -pub struct Client -where - R: Send + Sync + Copy + Spawner + 'static, -{ - socket: DuplexSocket, +pub struct Client { + socket: DuplexSocket, } -pub struct ClientBuilder +pub struct ClientBuilder where - T: Send + Sync + ClientTransport + 'static, + T: Send + Sync + Transport + 'static, + C: Send + Sync + Connection + 'static, { transport: Option, setup: SetupPayloadBuilder, @@ -34,11 +32,12 @@ where mtu: usize, } -impl ClientBuilder +impl ClientBuilder where - T: Send + Sync + ClientTransport + 'static, + T: Send + Sync + Transport + 'static, + C: Send + Sync + Connection + 'static, { - pub(crate) fn new() -> ClientBuilder { + pub(crate) fn new() -> ClientBuilder { ClientBuilder { transport: None, responder: None, @@ -106,64 +105,75 @@ where self } - pub async fn start(self) -> Result, Box> { - self.start_with_runtime(DefaultSpawner).await - } + pub async fn start(mut self) -> Result { + let tp: T = self.transport.take().expect("missint transport"); - pub async fn start_with_runtime( - mut self, - rt: R, - ) -> Result, Box> - where - R: Send + Sync + Copy + Spawner + 'static, - { - let tp = self.transport.take().expect("missint transport"); - let (rcv_tx, rcv_rx) = mpsc::unbounded::(); - let (snd_tx, snd_rx) = mpsc::unbounded::(); - let (connected_tx, connected_rx) = oneshot::channel::>(); - tp.attach(rcv_tx, snd_rx, Some(connected_tx)); - connected_rx.await??; let splitter = if self.mtu == 0 { None } else { Some(Splitter::new(self.mtu)) }; - let duplex_socket = DuplexSocket::new(rt, 1, snd_tx.clone(), splitter).await; - let cloned_duplex_socket = duplex_socket.clone(); + + let (snd_tx, mut snd_rx) = mpsc::channel::(super::CHANNEL_SIZE); + let mut socket = DuplexSocket::new(1, snd_tx, splitter).await; + + let mut cloned_socket = socket.clone(); let acceptor: Option = match self.responder { Some(it) => Some(Acceptor::Simple(Arc::new(it))), None => None, }; + + let conn = tp.connect().await?; + let (mut sink, mut stream) = conn.split(); + + runtime::spawn(async move { + while let Some(frame) = snd_rx.next().await { + if let Err(e) = (&mut sink).write(frame).await { + error!("write frame failed: {}", e); + break; + } + } + }); + let closer = self.closer.take(); - rt.spawn(async move { - cloned_duplex_socket.event_loop(acceptor, rcv_rx).await; + runtime::spawn(async move { + while let Some(next) = stream.read().await { + match next { + Ok(frame) => { + if let Err(e) = cloned_socket.dispatch(frame, &acceptor).await { + error!("dispatch frame failed: {}", e); + break; + } + } + Err(e) => { + error!("read next frame failed: {}", e); + break; + } + } + } if let Some(mut invoke) = closer { invoke(); } }); - let setup = self.setup.build(); - duplex_socket.setup(setup).await; - Ok(Client::new(duplex_socket)) + + socket.setup(self.setup.build()).await; + Ok(Client::from(socket)) } } -impl Client -where - R: Send + Sync + Copy + Spawner + 'static, -{ - fn new(socket: DuplexSocket) -> Client { +impl From for Client { + fn from(socket: DuplexSocket) -> Client { Client { socket } } +} +impl Client { pub fn close(self) { - self.socket.close(); + // TODO: support close } } -impl RSocket for Client -where - R: Send + Sync + Copy + Spawner + 'static, -{ +impl RSocket for Client { fn metadata_push(&self, req: Payload) -> Mono<()> { self.socket.metadata_push(req) } @@ -172,18 +182,15 @@ where self.socket.fire_and_forget(req) } - fn request_response(&self, req: Payload) -> Mono> { + fn request_response(&self, req: Payload) -> Mono> { self.socket.request_response(req) } - fn request_stream(&self, req: Payload) -> Flux> { + fn request_stream(&self, req: Payload) -> Flux> { self.socket.request_stream(req) } - fn request_channel( - &self, - reqs: Flux>, - ) -> Flux> { + fn request_channel(&self, reqs: Flux>) -> Flux> { self.socket.request_channel(reqs) } } diff --git a/rsocket/src/core/factory.rs b/rsocket/src/core/factory.rs new file mode 100644 index 0000000..af9445d --- /dev/null +++ b/rsocket/src/core/factory.rs @@ -0,0 +1,23 @@ +use super::{Client, ClientBuilder, ServerBuilder}; +use crate::transport::{Connection, ServerTransport, Transport}; + +#[derive(Debug)] +pub struct RSocketFactory; + +impl RSocketFactory { + pub fn connect() -> ClientBuilder + where + T: Send + Sync + Transport, + C: Send + Sync + Connection, + { + ClientBuilder::new() + } + + pub fn receive() -> ServerBuilder + where + S: Send + Sync + ServerTransport + 'static, + T: Send + Sync + Transport + 'static, + { + ServerBuilder::new() + } +} diff --git a/rsocket/src/x/mod.rs b/rsocket/src/core/mod.rs similarity index 76% rename from rsocket/src/x/mod.rs rename to rsocket/src/core/mod.rs index 9730794..c778404 100644 --- a/rsocket/src/x/mod.rs +++ b/rsocket/src/core/mod.rs @@ -2,6 +2,8 @@ mod client; mod factory; mod server; +pub(crate) const CHANNEL_SIZE: usize = 32; + pub use client::{Client, ClientBuilder}; pub use factory::RSocketFactory; pub use server::ServerBuilder; diff --git a/rsocket/src/core/server.rs b/rsocket/src/core/server.rs new file mode 100644 index 0000000..bd9c3b0 --- /dev/null +++ b/rsocket/src/core/server.rs @@ -0,0 +1,146 @@ +use crate::error::RSocketError; +use crate::frame::{self, Frame}; +use crate::payload::SetupPayload; +use crate::runtime; +use crate::spi::{EmptyRSocket, RSocket, ServerResponder}; +use crate::transport::{ + Acceptor, Connection, DuplexSocket, ServerTransport, Splitter, Transport, MIN_MTU, +}; +use crate::Result; +use std::error::Error; +use std::future::Future; +use std::net::SocketAddr; +use std::pin::Pin; +use std::sync::Arc; +use tokio::sync::mpsc; + +pub struct ServerBuilder +where + T: Send + Sync + ServerTransport, + C: Send + Sync + Transport, +{ + transport: Option, + on_setup: Option, + start_handler: Option>, + mtu: usize, +} + +impl ServerBuilder +where + T: Send + Sync + ServerTransport + 'static, + C: Send + Sync + Transport + 'static, +{ + pub(crate) fn new() -> ServerBuilder { + ServerBuilder { + transport: None, + on_setup: None, + start_handler: None, + mtu: 0, + } + } + + pub fn fragment(mut self, mtu: usize) -> Self { + if mtu > 0 && mtu < MIN_MTU { + panic!("invalid fragment mtu: at least {}!", MIN_MTU) + } + self.mtu = mtu; + self + } + + pub fn acceptor(mut self, handler: ServerResponder) -> Self { + self.on_setup = Some(handler); + self + } + + pub fn on_start(mut self, hanlder: Box) -> Self { + self.start_handler = Some(hanlder); + self + } + + pub fn transport(mut self, transport: T) -> Self { + self.transport = Some(transport); + self + } + + pub async fn serve(mut self) -> Result<()> { + let mut server_transport = self.transport.take().expect("missing transport"); + + let acceptor = match self.on_setup { + Some(v) => Some(Acceptor::Generate(Arc::new(v))), + None => None, + }; + + let mtu = self.mtu; + + server_transport.start().await?; + + if let Some(mut invoke) = self.start_handler { + invoke(); + } + + while let Some(next) = server_transport.next().await { + match next { + Ok(tp) => { + let acceptor = acceptor.clone(); + runtime::spawn(async move { + if let Err(e) = Self::on_transport(mtu, tp, acceptor).await { + error!("handle transport failed: {}", e); + } + }); + } + Err(e) => { + error!("accept next transport failed: {}", e); + } + } + } + Ok(()) + } + + #[inline] + async fn on_transport(mtu: usize, tp: C, acceptor: Option) -> Result<()> { + // Establish connection. + let conn = tp.connect().await?; + let (mut writer, mut reader) = conn.split(); + + // Create frame splitter. + let splitter = if mtu != 0 { + Some(Splitter::new(mtu)) + } else { + None + }; + + // Init duplex socket. + let (snd_tx, mut snd_rx) = mpsc::channel::(super::CHANNEL_SIZE); + let mut socket = DuplexSocket::new(0, snd_tx, splitter).await; + + // Begin loop for writing frames. + runtime::spawn(async move { + while let Some(frame) = snd_rx.recv().await { + if let Err(e) = writer.write(frame).await { + error!("write frame failed: {}", e); + break; + } + } + }); + + loop { + match reader.read().await { + Some(Ok(frame)) => { + if let Err(e) = socket.dispatch(frame, &acceptor).await { + error!("dispatch incoming frame failed: {}", e); + break; + } + } + Some(Err(e)) => { + error!("read next frame failed: {}", e); + break; + } + None => { + break; + } + } + } + + Ok(()) + } +} diff --git a/rsocket/src/error.rs b/rsocket/src/error.rs index b4819b1..7d51ee9 100644 --- a/rsocket/src/error.rs +++ b/rsocket/src/error.rs @@ -20,6 +20,7 @@ pub enum ErrorKind { IO(io::Error), Cancelled(), LengthTooShort(usize), + InComplete, } #[derive(Debug)] @@ -37,6 +38,7 @@ impl fmt::Display for RSocketError { ErrorKind::IO(e) => write!(f, "{}", e), ErrorKind::Cancelled() => write!(f, "ERROR(CANCELLED)"), ErrorKind::LengthTooShort(n) => write!(f, "ERROR(MINIMAL LENGTH {})", n), + ErrorKind::InComplete => write!(f, "INCOMPLETE"), } } } diff --git a/rsocket/src/extension/composite.rs b/rsocket/src/extension/composite.rs index 4398c9c..3b28d9b 100644 --- a/rsocket/src/extension/composite.rs +++ b/rsocket/src/extension/composite.rs @@ -1,6 +1,6 @@ use super::mime::MimeType; use crate::error::{ErrorKind, RSocketError}; -use crate::utils::{u24, RSocketResult, Writeable}; +use crate::utils::{u24, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::collections::LinkedList; use std::convert::TryFrom; @@ -92,7 +92,7 @@ impl CompositeMetadata { } } - pub fn decode(b: &mut BytesMut) -> RSocketResult { + pub fn decode(b: &mut BytesMut) -> crate::Result { let mut metadatas = LinkedList::new(); loop { match Self::decode_once(b) { @@ -109,7 +109,7 @@ impl CompositeMetadata { } #[inline] - fn decode_once(bs: &mut BytesMut) -> RSocketResult> { + fn decode_once(bs: &mut BytesMut) -> crate::Result> { if bs.is_empty() { return Ok(None); } @@ -121,32 +121,27 @@ impl CompositeMetadata { Some(well) => well, None => { let err_str = format!("invalid Well-Known MIME type: identifier={:x}", n); - return Err(RSocketError::from(err_str)); + return Err(err_str.into()); } } } else { // Bad let mime_len = (first as usize) + 1; if bs.len() < mime_len { - return Err(RSocketError::from( - "broken composite metadata: empty MIME type!", - )); + return Err("broken composite metadata: empty MIME type!".into()); } let front = bs.split_to(mime_len); MimeType::Normal(String::from_utf8(front.to_vec()).unwrap()) }; if bs.len() < 3 { - return Err(RSocketError::from( - "broken composite metadata: not enough bytes!", - )); + return Err("broken composite metadata: not enough bytes!".into()); } let payload_size = u24::read_advance(bs).into(); if bs.len() < payload_size { - return Err(RSocketError::from(format!( - "broken composite metadata: require {} bytes!", - payload_size - ))); + return Err( + format!("broken composite metadata: require {} bytes!", payload_size).into(), + ); } let metadata = bs.split_to(payload_size).freeze(); Ok(Some(CompositeMetadataEntry::new(mime_type, metadata))) diff --git a/rsocket/src/extension/mime.rs b/rsocket/src/extension/mime.rs index 47ffb22..e408785 100644 --- a/rsocket/src/extension/mime.rs +++ b/rsocket/src/extension/mime.rs @@ -1,5 +1,4 @@ use std::collections::HashMap; -use std::error::Error; use std::fmt; #[derive(PartialEq, Eq, Debug, Clone, Hash)] diff --git a/rsocket/src/extension/routing.rs b/rsocket/src/extension/routing.rs index 5afe600..56a4136 100644 --- a/rsocket/src/extension/routing.rs +++ b/rsocket/src/extension/routing.rs @@ -1,5 +1,5 @@ use crate::error::{ErrorKind, RSocketError}; -use crate::utils::{RSocketResult, Writeable}; +use crate::utils::Writeable; use bytes::{Buf, BufMut, Bytes, BytesMut}; const MAX_ROUTING_TAG_LEN: usize = 0xFF; @@ -37,7 +37,7 @@ impl RoutingMetadata { } } - pub fn decode(bf: &mut BytesMut) -> RSocketResult { + pub fn decode(bf: &mut BytesMut) -> crate::Result { let mut bu = RoutingMetadata::builder(); loop { match Self::decode_once(bf) { @@ -55,13 +55,13 @@ impl RoutingMetadata { &self.tags } - fn decode_once(bf: &mut BytesMut) -> RSocketResult> { + fn decode_once(bf: &mut BytesMut) -> crate::Result> { if bf.is_empty() { return Ok(None); } let size = bf.get_u8() as usize; if bf.len() < size { - return Err(RSocketError::from("require more bytes!")); + return Err("require more bytes!".into()); } let tag = String::from_utf8(bf.split_to(size).to_vec()).unwrap(); Ok(Some(tag)) diff --git a/rsocket/src/frame/error.rs b/rsocket/src/frame/error.rs index 86943cc..e8cae2c 100644 --- a/rsocket/src/frame/error.rs +++ b/rsocket/src/frame/error.rs @@ -1,6 +1,6 @@ use super::utils::too_short; use super::{Body, Frame}; -use crate::utils::{RSocketResult, Writeable}; +use crate::utils::Writeable; use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::fmt; @@ -44,7 +44,7 @@ impl ErrorBuilder { } impl Error { - pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> crate::Result { if bf.len() < 4 { too_short(4) } else { diff --git a/rsocket/src/frame/keepalive.rs b/rsocket/src/frame/keepalive.rs index f25d586..562794e 100644 --- a/rsocket/src/frame/keepalive.rs +++ b/rsocket/src/frame/keepalive.rs @@ -1,6 +1,6 @@ use super::utils::too_short; use super::{Body, Frame}; -use crate::utils::{RSocketResult, Writeable}; +use crate::utils::Writeable; use bytes::{Buf, BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] @@ -43,7 +43,7 @@ impl KeepaliveBuilder { } impl Keepalive { - pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> crate::Result { if bf.len() < 8 { return too_short(8); } diff --git a/rsocket/src/frame/lease.rs b/rsocket/src/frame/lease.rs index 847ef33..fc0fd48 100644 --- a/rsocket/src/frame/lease.rs +++ b/rsocket/src/frame/lease.rs @@ -1,6 +1,6 @@ use super::utils::too_short; use super::{Body, Frame}; -use crate::utils::{RSocketResult, Writeable}; +use crate::utils::Writeable; use bytes::{Buf, BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] @@ -51,7 +51,7 @@ impl LeaseBuilder { } impl Lease { - pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> crate::Result { if bf.len() < 8 { return too_short(8); } diff --git a/rsocket/src/frame/metadata_push.rs b/rsocket/src/frame/metadata_push.rs index 3d4939a..5db9aae 100644 --- a/rsocket/src/frame/metadata_push.rs +++ b/rsocket/src/frame/metadata_push.rs @@ -1,5 +1,5 @@ use super::{Body, Frame}; -use crate::utils::{RSocketResult, Writeable}; +use crate::utils::Writeable; use bytes::{Buf, BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] @@ -33,7 +33,7 @@ impl MetadataPushBuiler { } impl MetadataPush { - pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> crate::Result { let m = Bytes::from(bf.to_vec()); Ok(MetadataPush { metadata: Some(m) }) } diff --git a/rsocket/src/frame/mod.rs b/rsocket/src/frame/mod.rs index 64ed12a..12f1b5d 100644 --- a/rsocket/src/frame/mod.rs +++ b/rsocket/src/frame/mod.rs @@ -1,5 +1,5 @@ use crate::error::{ErrorKind, RSocketError}; -use crate::utils::{RSocketResult, Writeable}; +use crate::utils::Writeable; use bytes::{Buf, BufMut, Bytes, BytesMut}; mod cancel; @@ -143,9 +143,9 @@ impl Frame { } } - pub fn decode(b: &mut BytesMut) -> RSocketResult { + pub fn decode(b: &mut BytesMut) -> crate::Result { if b.len() < LEN_HEADER { - return Err(ErrorKind::LengthTooShort(LEN_HEADER).into()); + return Err(Box::new(RSocketError::from(ErrorKind::InComplete))); } let sid = b.get_u32(); let n = b.get_u16(); @@ -167,7 +167,7 @@ impl Frame { Self::TYPE_ERROR => Error::decode(flag, b).map(Body::Error), Self::TYPE_RESUME_OK => ResumeOK::decode(flag, b).map(Body::ResumeOK), Self::TYPE_RESUME => Resume::decode(flag, b).map(Body::Resume), - _ => Err(RSocketError::from(format!("illegal frame type: {}", kind))), + _ => Err(format!("illegal frame type: {}", kind).into()), }; body.map(|it| Frame::new(sid, it, flag)) } diff --git a/rsocket/src/frame/payload.rs b/rsocket/src/frame/payload.rs index 8ff6b3f..6a7e923 100644 --- a/rsocket/src/frame/payload.rs +++ b/rsocket/src/frame/payload.rs @@ -1,6 +1,7 @@ use super::utils; use super::{Body, Frame}; -use crate::utils::{RSocketResult, Writeable}; +use crate::utils::Writeable; +use crate::Result; use bytes::{BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] @@ -59,7 +60,7 @@ impl PayloadBuilder { } impl Payload { - pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> Result { utils::read_payload(flag, bf).map(|(metadata, data)| Payload { metadata, data }) } diff --git a/rsocket/src/frame/request_channel.rs b/rsocket/src/frame/request_channel.rs index 82e5c5c..a652b1e 100644 --- a/rsocket/src/frame/request_channel.rs +++ b/rsocket/src/frame/request_channel.rs @@ -1,6 +1,6 @@ use super::utils; use super::{Body, Frame, REQUEST_MAX}; -use crate::utils::{RSocketResult, Writeable}; +use crate::utils::Writeable; use bytes::{Buf, BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] @@ -66,7 +66,7 @@ impl RequestChannelBuilder { } impl RequestChannel { - pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> crate::Result { if bf.len() < 4 { utils::too_short(4) } else { diff --git a/rsocket/src/frame/request_fnf.rs b/rsocket/src/frame/request_fnf.rs index b4a26cc..30c9d1e 100644 --- a/rsocket/src/frame/request_fnf.rs +++ b/rsocket/src/frame/request_fnf.rs @@ -1,5 +1,5 @@ use super::{utils, Body, Frame}; -use crate::utils::{RSocketResult, Writeable}; +use crate::utils::Writeable; use bytes::{BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] @@ -58,7 +58,7 @@ impl RequestFNFBuilder { } impl RequestFNF { - pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> crate::Result { utils::read_payload(flag, bf).map(|(m, d)| RequestFNF { metadata: m, data: d, diff --git a/rsocket/src/frame/request_n.rs b/rsocket/src/frame/request_n.rs index db59fc7..989af66 100644 --- a/rsocket/src/frame/request_n.rs +++ b/rsocket/src/frame/request_n.rs @@ -1,5 +1,5 @@ use super::{utils, Body, Frame, REQUEST_MAX}; -use crate::utils::{RSocketResult, Writeable}; +use crate::utils::Writeable; use bytes::{Buf, BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] @@ -33,7 +33,7 @@ impl RequestNBuilder { } impl RequestN { - pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> crate::Result { if bf.len() < 4 { utils::too_short(4) } else { diff --git a/rsocket/src/frame/request_response.rs b/rsocket/src/frame/request_response.rs index 0d3b4d9..df10bbb 100644 --- a/rsocket/src/frame/request_response.rs +++ b/rsocket/src/frame/request_response.rs @@ -1,5 +1,5 @@ use super::{utils, Body, Frame}; -use crate::utils::{RSocketResult, Writeable}; +use crate::utils::Writeable; use bytes::{BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] @@ -58,7 +58,7 @@ impl RequestResponseBuilder { } impl RequestResponse { - pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> crate::Result { utils::read_payload(flag, bf).map(|(m, d)| RequestResponse { metadata: m, data: d, diff --git a/rsocket/src/frame/request_stream.rs b/rsocket/src/frame/request_stream.rs index 23412ed..b451df8 100644 --- a/rsocket/src/frame/request_stream.rs +++ b/rsocket/src/frame/request_stream.rs @@ -1,5 +1,5 @@ use super::{utils, Body, Frame, REQUEST_MAX}; -use crate::utils::{RSocketResult, Writeable}; +use crate::utils::Writeable; use bytes::{Buf, BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] @@ -53,7 +53,7 @@ impl RequestStreamBuilder { } impl RequestStream { - pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> crate::Result { if bf.len() < 4 { utils::too_short(4) } else { diff --git a/rsocket/src/frame/resume.rs b/rsocket/src/frame/resume.rs index 164a3c6..cf70a17 100644 --- a/rsocket/src/frame/resume.rs +++ b/rsocket/src/frame/resume.rs @@ -1,6 +1,6 @@ use super::utils::too_short; use super::{Body, Frame, Version}; -use crate::utils::{RSocketResult, Writeable}; +use crate::utils::Writeable; use bytes::{Buf, BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] @@ -27,7 +27,7 @@ impl Resume { } } - pub(crate) fn decode(flag: u16, b: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, b: &mut BytesMut) -> crate::Result { if b.len() < 6 { return too_short(6); } diff --git a/rsocket/src/frame/resume_ok.rs b/rsocket/src/frame/resume_ok.rs index 1dd2d1e..aac2162 100644 --- a/rsocket/src/frame/resume_ok.rs +++ b/rsocket/src/frame/resume_ok.rs @@ -1,6 +1,6 @@ use super::utils::too_short; use super::{Body, Frame}; -use crate::utils::{RSocketResult, Writeable}; +use crate::utils::Writeable; use bytes::{Buf, BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] @@ -33,7 +33,7 @@ impl ResumeOKBuilder { } impl ResumeOK { - pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> crate::Result { if bf.len() < 8 { too_short(8) } else { diff --git a/rsocket/src/frame/setup.rs b/rsocket/src/frame/setup.rs index a163cdc..f033506 100644 --- a/rsocket/src/frame/setup.rs +++ b/rsocket/src/frame/setup.rs @@ -1,6 +1,6 @@ use super::utils::{self, too_short}; use super::{Body, Frame, Version}; -use crate::utils::{RSocketResult, Writeable, DEFAULT_MIME_TYPE}; +use crate::utils::{Writeable, DEFAULT_MIME_TYPE}; use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::time::Duration; @@ -23,7 +23,7 @@ pub struct SetupBuilder { } impl Setup { - pub(crate) fn decode(flag: u16, b: &mut BytesMut) -> RSocketResult { + pub(crate) fn decode(flag: u16, b: &mut BytesMut) -> crate::Result { // Check minimal length: version(4bytes) + keepalive(4bytes) + lifetime(4bytes) if b.len() < 12 { return too_short(12); diff --git a/rsocket/src/frame/utils.rs b/rsocket/src/frame/utils.rs index 448ce34..714ed70 100644 --- a/rsocket/src/frame/utils.rs +++ b/rsocket/src/frame/utils.rs @@ -1,12 +1,12 @@ use super::Frame; use crate::error::{ErrorKind, RSocketError}; -use crate::utils::{u24, RSocketResult, Writeable}; +use crate::utils::{u24, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; pub(crate) fn read_payload( flag: u16, bf: &mut BytesMut, -) -> RSocketResult<(Option, Option)> { +) -> crate::Result<(Option, Option)> { let m: Option = if flag & Frame::FLAG_METADATA != 0 { if bf.len() < 3 { return too_short(3); @@ -38,6 +38,6 @@ pub(crate) fn write_payload(bf: &mut BytesMut, metadata: Option<&Bytes>, data: O } } -pub(crate) fn too_short(n: usize) -> RSocketResult { - Err(ErrorKind::LengthTooShort(n).into()) +pub(crate) fn too_short(n: usize) -> crate::Result { + Err(Box::new(RSocketError::from(ErrorKind::LengthTooShort(n)))) } diff --git a/rsocket/src/lib.rs b/rsocket/src/lib.rs index 468c04d..d45f4ee 100644 --- a/rsocket/src/lib.rs +++ b/rsocket/src/lib.rs @@ -102,10 +102,16 @@ pub mod frame; #[cfg(not(feature = "frame"))] mod frame; +mod core; mod payload; pub mod prelude; pub mod runtime; mod spi; pub mod transport; pub mod utils; -mod x; + +pub type Error = Box; +pub type Result = std::result::Result; +pub type PinBoxFuture = std::pin::Pin>>; + +pub use crate::core::{Client, ClientBuilder, ServerBuilder}; diff --git a/rsocket/src/payload/normal.rs b/rsocket/src/payload/normal.rs index 8189ffb..e1987c8 100644 --- a/rsocket/src/payload/normal.rs +++ b/rsocket/src/payload/normal.rs @@ -51,7 +51,7 @@ impl PayloadBuilder { } impl Payload { - pub(crate) fn new(data: Option, metadata: Option) -> Payload { + pub fn new(data: Option, metadata: Option) -> Payload { Payload { d: data, m: metadata, diff --git a/rsocket/src/prelude.rs b/rsocket/src/prelude.rs index 6ac8fae..03cb1b8 100644 --- a/rsocket/src/prelude.rs +++ b/rsocket/src/prelude.rs @@ -1,7 +1,5 @@ +pub use crate::core::RSocketFactory; pub use crate::payload::{Payload, PayloadBuilder, SetupPayload, SetupPayloadBuilder}; -pub use crate::runtime::Spawner; pub use crate::spi::*; -pub use crate::transport::{ClientTransport, Rx, ServerTransport, Tx}; -pub use crate::utils::RSocketResult; -pub use crate::x::{Client, RSocketFactory}; +pub use crate::transport::{ServerTransport, Transport}; pub use futures::{Sink, SinkExt, Stream, StreamExt}; diff --git a/rsocket/src/runtime/mod.rs b/rsocket/src/runtime/mod.rs index d5dd24f..c6e150a 100644 --- a/rsocket/src/runtime/mod.rs +++ b/rsocket/src/runtime/mod.rs @@ -1,19 +1,17 @@ use std::future::Future; -pub trait Spawner { - fn spawn(&self, task: F) - where - F: Send + Future + 'static; -} - -#[derive(Clone, Copy, Debug)] -pub struct DefaultSpawner; - -impl Spawner for DefaultSpawner { - fn spawn(&self, task: F) - where - F: Send + Future + 'static, +pub fn spawn(task: F) +where + F: Send + Future + 'static, +{ + #[cfg(not(target_arch = "wasm32"))] { tokio::spawn(task); } + + #[cfg(target_arch = "wasm32")] + { + use wasm_bindgen_futures::spawn_local; + spawn_local(task); + } } diff --git a/rsocket/src/spi.rs b/rsocket/src/spi.rs index 37fa213..589d9d2 100644 --- a/rsocket/src/spi.rs +++ b/rsocket/src/spi.rs @@ -1,22 +1,16 @@ use crate::error::{self, ErrorKind, RSocketError}; -use crate::frame; use crate::payload::{Payload, SetupPayload}; -use crate::utils::RSocketResult; +use crate::{runtime, Error, Result}; use futures::future; -use futures::{Sink, SinkExt, Stream, StreamExt}; -use std::error::Error; +use futures::{pin_mut, FutureExt, Sink, SinkExt, Stream, StreamExt}; use std::future::Future; use std::pin::Pin; -use std::result::Result; use std::sync::Arc; use tokio::sync::mpsc; pub type ClientResponder = Box Box>; -pub type ServerResponder = Box< - dyn Send - + Sync - + Fn(SetupPayload, Box) -> Result, Box>, ->; +pub type ServerResponder = + Box) -> Result>>; pub type Mono = Pin>>; pub type Flux = Pin>>; @@ -24,12 +18,9 @@ pub type Flux = Pin>>; pub trait RSocket: Sync + Send { fn metadata_push(&self, req: Payload) -> Mono<()>; fn fire_and_forget(&self, req: Payload) -> Mono<()>; - fn request_response(&self, req: Payload) -> Mono>; - fn request_stream(&self, req: Payload) -> Flux>; - fn request_channel( - &self, - reqs: Flux>, - ) -> Flux>; + fn request_response(&self, req: Payload) -> Mono>; + fn request_stream(&self, req: Payload) -> Flux>; + fn request_channel(&self, reqs: Flux>) -> Flux>; } pub struct EchoRSocket; @@ -45,12 +36,12 @@ impl RSocket for EchoRSocket { Box::pin(async {}) } - fn request_response(&self, req: Payload) -> Mono> { + fn request_response(&self, req: Payload) -> Mono> { info!("{:?}", req); Box::pin(async move { Ok(req) }) } - fn request_stream(&self, req: Payload) -> Flux> { + fn request_stream(&self, req: Payload) -> Flux> { info!("{:?}", req); // repeat 3 times. Box::pin(futures::stream::iter(vec![ @@ -60,10 +51,7 @@ impl RSocket for EchoRSocket { ])) } - fn request_channel( - &self, - mut reqs: Flux>, - ) -> Flux> { + fn request_channel(&self, mut reqs: Flux>) -> Flux> { let (sender, receiver) = mpsc::unbounded_channel(); tokio::spawn(async move { while let Some(it) = reqs.next().await { @@ -80,9 +68,10 @@ impl RSocket for EchoRSocket { pub(crate) struct EmptyRSocket; impl EmptyRSocket { - fn must_failed(&self) -> RSocketError { + #[inline] + fn must_failed(&self) -> Error { let kind = ErrorKind::Internal(error::ERR_APPLICATION, String::from("NOT_IMPLEMENT")); - RSocketError::from(kind) + Box::new(RSocketError::from(kind)) } } @@ -95,18 +84,15 @@ impl RSocket for EmptyRSocket { Box::pin(async {}) } - fn request_response(&self, _req: Payload) -> Mono> { + fn request_response(&self, _req: Payload) -> Mono> { Box::pin(future::err(self.must_failed())) } - fn request_stream(&self, _req: Payload) -> Flux> { + fn request_stream(&self, _req: Payload) -> Flux> { Box::pin(futures::stream::empty()) } - fn request_channel( - &self, - _reqs: Flux>, - ) -> Flux> { + fn request_channel(&self, _reqs: Flux>) -> Flux> { Box::pin(futures::stream::empty()) } } diff --git a/rsocket/src/transport/misc.rs b/rsocket/src/transport/misc.rs index 04f3c2c..06b0fc9 100644 --- a/rsocket/src/transport/misc.rs +++ b/rsocket/src/transport/misc.rs @@ -2,7 +2,6 @@ use crate::error::{ErrorKind, RSocketError}; use crate::frame::{self}; use crate::payload::{Payload, SetupPayload}; use crate::spi::RSocket; -use crate::utils::RSocketResult; use futures::future; use std::collections::HashMap; use std::future::Future; diff --git a/rsocket/src/transport/socket.rs b/rsocket/src/transport/socket.rs index 3e5634b..86ce82e 100644 --- a/rsocket/src/transport/socket.rs +++ b/rsocket/src/transport/socket.rs @@ -1,35 +1,29 @@ use super::fragmentation::{Joiner, Splitter}; -use super::misc::{self, Counter, StreamID}; +use super::misc::{debug_frame, Counter, StreamID}; use super::spi::*; use crate::error::{self, ErrorKind, RSocketError}; use crate::frame::{self, Body, Frame}; use crate::payload::{Payload, SetupPayload}; -use crate::runtime::Spawner; use crate::spi::{EmptyRSocket, Flux, Mono, RSocket}; -use crate::utils::RSocketResult; +use crate::{runtime, Result}; use bytes::{Buf, BufMut, Bytes, BytesMut}; -use futures::{future, Sink, SinkExt, Stream, StreamExt}; -use std::collections::{hash_map::Entry, HashMap}; -use std::env; -use std::error::Error; +use dashmap::{mapref::entry::Entry, DashMap}; +use futures::{Sink, SinkExt, Stream, StreamExt}; use std::future::Future; use std::pin::Pin; -use std::ptr; -use std::result::Result; use std::sync::{Arc, RwLock}; use tokio::prelude::*; -use tokio::sync::Mutex; +use tokio::sync::{mpsc, oneshot}; #[derive(Clone)] -pub(crate) struct DuplexSocket { - rt: R, +pub(crate) struct DuplexSocket { seq: StreamID, responder: Responder, - tx: Tx, - handlers: [Arc>>; 16], - canceller: Tx, + tx: mpsc::Sender, + handlers: Arc>, + canceller: mpsc::Sender, splitter: Option, - joiners: Arc>>, + joiners: Arc>, } #[derive(Clone)] @@ -39,64 +33,39 @@ struct Responder { #[derive(Debug)] enum Handler { - ReqRR(TxOnce>), + ReqRR(oneshot::Sender>), ResRR(Counter), - ReqRS(Tx>), - ReqRC(Tx>), + ReqRS(mpsc::Sender>), + ReqRC(mpsc::Sender>), } -impl DuplexSocket -where - R: Send + Sync + Copy + Spawner + 'static, -{ +impl DuplexSocket { pub(crate) async fn new( - rt: R, first_stream_id: u32, - tx: Tx, + tx: mpsc::Sender, splitter: Option, - ) -> DuplexSocket { - let (canceller_tx, canceller_rx) = new_tx_rx::(); - let handlers = [ - Arc::new(Mutex::new(HashMap::new())), - Arc::new(Mutex::new(HashMap::new())), - Arc::new(Mutex::new(HashMap::new())), - Arc::new(Mutex::new(HashMap::new())), - Arc::new(Mutex::new(HashMap::new())), - Arc::new(Mutex::new(HashMap::new())), - Arc::new(Mutex::new(HashMap::new())), - Arc::new(Mutex::new(HashMap::new())), - Arc::new(Mutex::new(HashMap::new())), - Arc::new(Mutex::new(HashMap::new())), - Arc::new(Mutex::new(HashMap::new())), - Arc::new(Mutex::new(HashMap::new())), - Arc::new(Mutex::new(HashMap::new())), - Arc::new(Mutex::new(HashMap::new())), - Arc::new(Mutex::new(HashMap::new())), - Arc::new(Mutex::new(HashMap::new())), - ]; - let duplex_socket = DuplexSocket { - rt, + ) -> DuplexSocket { + let (canceller_tx, canceller_rx) = mpsc::channel::(32); + let socket = DuplexSocket { seq: StreamID::from(first_stream_id), tx, canceller: canceller_tx, responder: Responder::new(), - handlers, - joiners: Arc::new(Mutex::new(HashMap::new())), + handlers: Arc::new(DashMap::new()), + joiners: Arc::new(DashMap::new()), splitter, }; - let cloned_duplex_socket = duplex_socket.clone(); - rt.spawn(async move { - cloned_duplex_socket.loop_canceller(canceller_rx).await; + let cloned_socket = socket.clone(); + + runtime::spawn(async move { + cloned_socket.loop_canceller(canceller_rx).await; }); - duplex_socket - } - pub(crate) fn close(self) { - drop(self.tx); + socket } - pub(crate) async fn setup(&self, setup: SetupPayload) { + pub(crate) async fn setup(&mut self, setup: SetupPayload) { let mut bu = frame::Setup::builder(0, 0); if let Some(s) = setup.data_mime_type() { bu = bu.set_mime_data(s); @@ -113,36 +82,37 @@ where if let Some(b) = m { bu = bu.set_metadata(b); } - self.tx - .unbounded_send(bu.build()) - .expect("Send setup failed"); + self.tx.send(bu.build()).await.expect("Send setup failed"); } #[inline] - fn get_handler(&self, sid: u32) -> &Arc>> { - let i = ((sid ^ (sid >> 16)) & 15) as usize; - &self.handlers[i] + async fn register_handler(&self, sid: u32, handler: Handler) { + self.handlers.insert(sid, handler); } #[inline] - async fn register_handler(&self, sid: u32, handler: Handler) { - let h = self.get_handler(sid); - let mut handlers = h.lock().await; - (*handlers).insert(sid, handler); + async fn loop_canceller(&self, mut rx: mpsc::Receiver) { + while let Some(sid) = rx.next().await { + self.handlers.remove(&sid); + } } - pub(crate) async fn loop_canceller(&self, mut rx: Rx) { - while let Some(sid) = rx.next().await { - let mut handlers = self.get_handler(sid).lock().await; - (*handlers).remove(&sid); + pub(crate) async fn dispatch( + &mut self, + frame: Frame, + acceptor: &Option, + ) -> Result<()> { + if let Some(frame) = self.join_frame(frame).await { + self.process_once(frame, acceptor).await; } + Ok(()) } #[inline] - async fn process_once(&self, msg: Frame, acceptor: &Option) { + async fn process_once(&mut self, msg: Frame, acceptor: &Option) { let sid = msg.get_stream_id(); let flag = msg.get_flag(); - misc::debug_frame(false, &msg); + debug_frame(false, &msg); match msg.get_body() { Body::Setup(v) => { if let Err(e) = self.on_setup(acceptor, sid, flag, SetupPayload::from(v)) { @@ -151,9 +121,7 @@ where .set_code(error::ERR_REJECT_SETUP) .set_data(Bytes::from(errmsg)) .build(); - self.tx - .unbounded_send(sending) - .expect("Reject setup failed"); + self.tx.send(sending).await.expect("Reject setup failed"); return; } } @@ -209,14 +177,6 @@ where } } - pub(crate) async fn event_loop(&self, acceptor: Option, mut rx: Rx) { - while let Some(next) = rx.next().await { - if let Some(f) = self.join_frame(next).await { - self.process_once(f, &acceptor).await - } - } - } - #[inline] async fn join_frame(&self, input: Frame) -> Option { let (is_follow, is_payload) = input.is_followable_or_payload(); @@ -224,11 +184,9 @@ where return Some(input); } let sid = input.get_stream_id(); - let mut joiners = self.joiners.lock().await; - if input.get_flag() & Frame::FLAG_FOLLOW != 0 { // TODO: check conflict - (*joiners) + self.joiners .entry(sid) .or_insert_with(Joiner::new) .push(input); @@ -239,9 +197,9 @@ where return Some(input); } - match (*joiners).remove(&sid) { + match self.joiners.remove(&sid) { None => Some(input), - Some(mut joiner) => { + Some((_, mut joiner)) => { joiner.push(input); let flag = joiner.get_flag(); let first = joiner.first(); @@ -292,35 +250,27 @@ where } #[inline] - async fn on_error(&self, sid: u32, flag: u16, input: frame::Error) { - { - let mut joiners = self.joiners.lock().await; - (*joiners).remove(&sid); - } + async fn on_error(&mut self, sid: u32, flag: u16, input: frame::Error) { + self.joiners.remove(&sid); // pick handler - let mut handlers = self.get_handler(sid).lock().await; - if let Some(handler) = (*handlers).remove(&sid) { + if let Some((_, handler)) = self.handlers.remove(&sid) { let kind = ErrorKind::Internal(input.get_code(), input.get_data_utf8().unwrap().to_owned()); - let e = Err(RSocketError::from(kind)); + let e: Result<_> = Err(Box::new(RSocketError::from(kind))); match handler { Handler::ReqRR(tx) => tx.send(e).expect("Send RR failed"), Handler::ResRR(_) => unreachable!(), - Handler::ReqRS(tx) => tx.unbounded_send(e).expect("Send RS failed"), - Handler::ReqRC(tx) => tx.unbounded_send(e).expect("Send RC failed"), + Handler::ReqRS(mut tx) => tx.send(e).await.expect("Send RS failed"), + Handler::ReqRC(mut tx) => tx.send(e).await.expect("Send RC failed"), } } } #[inline] - async fn on_cancel(&self, sid: u32, _flag: u16) { - { - let mut joiners = self.joiners.lock().await; - (*joiners).remove(&sid); - } - let mut handlers = self.get_handler(sid).lock().await; - if let Some(handler) = (*handlers).remove(&sid) { - let e = Err(RSocketError::from(ErrorKind::Cancelled())); + async fn on_cancel(&mut self, sid: u32, _flag: u16) { + self.joiners.remove(&sid); + if let Some((_, handler)) = self.handlers.remove(&sid) { + let e: Result<_> = Err(Box::new(RSocketError::from(ErrorKind::Cancelled()))); match handler { Handler::ReqRR(sender) => { info!("REQUEST_RESPONSE {} cancelled!", sid); @@ -341,10 +291,8 @@ where } #[inline] - async fn on_payload(&self, sid: u32, flag: u16, input: Payload) { - let mut handlers = self.get_handler(sid).lock().await; - // fire event! - match (*handlers).entry(sid) { + async fn on_payload(&mut self, sid: u32, flag: u16, input: Payload) { + match self.handlers.entry(sid) { Entry::Occupied(o) => { match o.get() { Handler::ReqRR(_) => match o.remove() { @@ -357,7 +305,9 @@ where Handler::ReqRS(sender) => { if flag & Frame::FLAG_NEXT != 0 { sender - .unbounded_send(Ok(input)) + .clone() + .send(Ok(input)) + .await .expect("Send payload response failed."); } if flag & Frame::FLAG_COMPLETE != 0 { @@ -368,7 +318,9 @@ where // TODO: support channel if flag & Frame::FLAG_NEXT != 0 { sender - .unbounded_send(Ok(input)) + .clone() + .send(Ok(input)) + .await .expect("Send payload response failed"); } if flag & Frame::FLAG_COMPLETE != 0 { @@ -377,7 +329,7 @@ where } } } - Entry::Vacant(v) => warn!("invalid payload id {}: no such request!", sid), + Entry::Vacant(_) => warn!("invalid payload id {}: no such request!", sid), } } @@ -388,7 +340,7 @@ where sid: u32, flag: u16, setup: SetupPayload, - ) -> Result<(), Box> { + ) -> Result<()> { match acceptor { None => { self.responder.set(Box::new(EmptyRSocket)); @@ -409,20 +361,20 @@ where } #[inline] - async fn on_fire_and_forget(&self, sid: u32, input: Payload) { - self.responder.clone().fire_and_forget(input).await + async fn on_fire_and_forget(&mut self, sid: u32, input: Payload) { + self.responder.fire_and_forget(input).await } #[inline] - async fn on_request_response(&self, sid: u32, _flag: u16, input: Payload) { + async fn on_request_response(&mut self, sid: u32, _flag: u16, input: Payload) { let responder = self.responder.clone(); - let canceller = self.canceller.clone(); - let tx = self.tx.clone(); + let mut canceller = self.canceller.clone(); + let mut tx = self.tx.clone(); let splitter = self.splitter.clone(); let counter = Counter::new(2); self.register_handler(sid, Handler::ResRR(counter.clone())) .await; - self.rt.spawn(async move { + runtime::spawn(async move { // TODO: use future select let result = responder.request_response(input).await; if counter.count_down() == 0 { @@ -431,26 +383,25 @@ where } // async remove canceller - canceller - .unbounded_send(sid) - .expect("Send canceller failed"); + canceller.send(sid).await.expect("Send canceller failed"); match result { Ok(res) => { Self::try_send_payload( &splitter, - &tx, + &mut tx, sid, res, Frame::FLAG_NEXT | Frame::FLAG_COMPLETE, - ); + ) + .await; } Err(e) => { let sending = frame::Error::builder(sid, 0) .set_code(error::ERR_APPLICATION) .set_data(Bytes::from("TODO: should be error details")) .build(); - if let Err(e) = tx.unbounded_send(sending) { + if let Err(e) = tx.send(sending).await { error!("respond REQUEST_RESPONSE failed: {}", e); } } @@ -461,28 +412,28 @@ where #[inline] async fn on_request_stream(&self, sid: u32, flag: u16, input: Payload) { let responder = self.responder.clone(); - let tx = self.tx.clone(); + let mut tx = self.tx.clone(); let splitter = self.splitter.clone(); - self.rt.spawn(async move { + runtime::spawn(async move { // TODO: support cancel let mut payloads = responder.request_stream(input); while let Some(next) = payloads.next().await { match next { Ok(it) => { - Self::try_send_payload(&splitter, &tx, sid, it, Frame::FLAG_NEXT); + Self::try_send_payload(&splitter, &mut tx, sid, it, Frame::FLAG_NEXT).await; } Err(e) => { let sending = frame::Error::builder(sid, 0) .set_code(error::ERR_APPLICATION) .set_data(Bytes::from(format!("{}", e))) .build(); - tx.unbounded_send(sending) - .expect("Send stream response failed"); + tx.send(sending).await.expect("Send stream response failed"); } }; } let complete = frame::Payload::builder(sid, Frame::FLAG_COMPLETE).build(); - tx.unbounded_send(complete) + tx.send(complete) + .await .expect("Send stream complete response failed"); }); } @@ -490,29 +441,29 @@ where #[inline] async fn on_request_channel(&self, sid: u32, flag: u16, first: Payload) { let responder = self.responder.clone(); - let tx = self.tx.clone(); - let (sender, receiver) = new_tx_rx::>(); - sender.unbounded_send(Ok(first)).unwrap(); + let mut tx = self.tx.clone(); + let (mut sender, receiver) = mpsc::channel::>(32); + sender.send(Ok(first)).await.expect("Send failed!"); self.register_handler(sid, Handler::ReqRC(sender)).await; - self.rt.spawn(async move { + runtime::spawn(async move { // respond client channel let mut outputs = responder.request_channel(Box::pin(receiver)); // TODO: support custom RequestN. let request_n = frame::RequestN::builder(sid, 0).build(); - if let Err(e) = tx.unbounded_send(request_n) { + if let Err(e) = tx.send(request_n).await { error!("respond REQUEST_N failed: {}", e); } while let Some(next) = outputs.next().await { let sending = match next { - Ok(v) => { - let (d, m) = v.split(); + Ok(payload) => { + let (data, metadata) = payload.split(); let mut bu = frame::Payload::builder(sid, Frame::FLAG_NEXT); - if let Some(b) = d { + if let Some(b) = data { bu = bu.set_data(b); } - if let Some(b) = m { + if let Some(b) = metadata { bu = bu.set_metadata(b); } bu.build() @@ -522,37 +473,36 @@ where .set_data(Bytes::from(format!("{}", e))) .build(), }; - tx.unbounded_send(sending).unwrap(); + tx.send(sending).await.expect("Send failed!"); } let complete = frame::Payload::builder(sid, Frame::FLAG_COMPLETE).build(); - if let Err(e) = tx.unbounded_send(complete) { + if let Err(e) = tx.send(complete).await { error!("complete REQUEST_CHANNEL failed: {}", e); } }); } #[inline] - async fn on_metadata_push(&self, input: Payload) { - self.responder.clone().metadata_push(input).await + async fn on_metadata_push(&mut self, input: Payload) { + self.responder.metadata_push(input).await } #[inline] - async fn on_keepalive(&self, keepalive: frame::Keepalive) { - let tx = self.tx.clone(); + async fn on_keepalive(&mut self, keepalive: frame::Keepalive) { let (data, _) = keepalive.split(); let mut sending = frame::Keepalive::builder(0, 0); if let Some(b) = data { sending = sending.set_data(b); } - if let Err(e) = tx.unbounded_send(sending.build()) { + if let Err(e) = self.tx.send(sending.build()).await { error!("respond KEEPALIVE failed: {}", e); } } #[inline] - fn try_send_channel( + async fn try_send_channel( splitter: &Option, - tx: &Tx, + tx: &mut mpsc::Sender, sid: u32, res: Payload, flag: u16, @@ -574,7 +524,7 @@ where .build() }; // send frame - if let Err(e) = tx.unbounded_send(sending) { + if let Err(e) = tx.send(sending).await { error!("send request_channel failed: {}", e); return; } @@ -595,7 +545,7 @@ where .build() }; // send frame - if let Err(e) = tx.unbounded_send(sending) { + if let Err(e) = tx.send(sending).await { error!("send request_channel failed: {}", e); } } @@ -603,7 +553,7 @@ where let sending = frame::RequestChannel::builder(sid, flag) .set_all(res.split()) .build(); - if let Err(e) = tx.unbounded_send(sending) { + if let Err(e) = tx.send(sending).await { error!("send request_channel failed: {}", e); } } @@ -611,9 +561,9 @@ where } #[inline] - fn try_send_payload( + async fn try_send_payload( splitter: &Option, - tx: &Tx, + tx: &mut mpsc::Sender, sid: u32, res: Payload, flag: u16, @@ -634,7 +584,7 @@ where .build() }; // send frame - if let Err(e) = tx.unbounded_send(sending) { + if let Err(e) = tx.send(sending).await { error!("send payload failed: {}", e); return; } @@ -651,7 +601,7 @@ where .build() }; // send frame - if let Err(e) = tx.unbounded_send(sending) { + if let Err(e) = tx.send(sending).await { error!("send payload failed: {}", e); } } @@ -659,7 +609,7 @@ where let sending = frame::Payload::builder(sid, flag) .set_all(res.split()) .build(); - if let Err(e) = tx.unbounded_send(sending) { + if let Err(e) = tx.send(sending).await { error!("respond failed: {}", e); } } @@ -667,27 +617,24 @@ where } } -impl RSocket for DuplexSocket -where - R: Send + Sync + Copy + Spawner + 'static, -{ +impl RSocket for DuplexSocket { fn metadata_push(&self, req: Payload) -> Mono<()> { let sid = self.seq.next(); - let tx = self.tx.clone(); + let mut tx = self.tx.clone(); Box::pin(async move { let (_d, m) = req.split(); let mut bu = frame::MetadataPush::builder(sid, 0); if let Some(b) = m { bu = bu.set_metadata(b); } - if let Err(e) = tx.unbounded_send(bu.build()) { + if let Err(e) = tx.send(bu.build()).await { error!("send metadata_push failed: {}", e); } }) } fn fire_and_forget(&self, req: Payload) -> Mono<()> { let sid = self.seq.next(); - let tx = self.tx.clone(); + let mut tx = self.tx.clone(); let splitter = self.splitter.clone(); Box::pin(async move { match splitter { @@ -708,7 +655,7 @@ where .build() }; // send frame - if let Err(e) = tx.unbounded_send(sending) { + if let Err(e) = tx.send(sending).await { error!("send fire_and_forget failed: {}", e); return; } @@ -729,7 +676,7 @@ where .build() }; // send frame - if let Err(e) = tx.unbounded_send(sending) { + if let Err(e) = tx.send(sending).await { error!("send fire_and_forget failed: {}", e); } } @@ -737,7 +684,7 @@ where let sending = frame::RequestFNF::builder(sid, 0) .set_all(req.split()) .build(); - if let Err(e) = tx.unbounded_send(sending) { + if let Err(e) = tx.send(sending).await { error!("send fire_and_forget failed: {}", e); } } @@ -745,21 +692,17 @@ where }) } - fn request_response(&self, req: Payload) -> Mono> { - let (tx, rx) = new_tx_rx_once::>(); + fn request_response(&self, req: Payload) -> Mono> { + let (tx, rx) = oneshot::channel::>(); let sid = self.seq.next(); - let handlers = Arc::clone(&self.get_handler(sid)); - let sender = self.tx.clone(); + let handlers = self.handlers.clone(); + let mut sender = self.tx.clone(); let splitter = self.splitter.clone(); - self.rt.spawn(async move { - { - // register handler - let mut map = handlers.lock().await; - (*map).insert(sid, Handler::ReqRR(tx)); - } - + runtime::spawn(async move { + // register handler + handlers.insert(sid, Handler::ReqRR(tx)); match splitter { Some(sp) => { let mut cuts: usize = 0; @@ -778,7 +721,7 @@ where .build() }; // send frame - if let Err(e) = sender.unbounded_send(sending) { + if let Err(e) = sender.send(sending).await { error!("send request_response failed: {}", e); return; } @@ -799,7 +742,7 @@ where .build() }; // send frame - if let Err(e) = sender.unbounded_send(sending) { + if let Err(e) = sender.send(sending).await { error!("send request_response failed: {}", e); } } @@ -809,7 +752,7 @@ where .set_all(req.split()) .build(); // send frame - if let Err(e) = sender.unbounded_send(sending) { + if let Err(e) = sender.send(sending).await { error!("send request_response failed: {}", e); } } @@ -818,23 +761,20 @@ where Box::pin(async move { match rx.await { Ok(v) => v, - Err(_e) => Err(RSocketError::from("request_response failed")), + Err(_e) => Err("request_response failed".into()), } }) } - fn request_stream(&self, input: Payload) -> Flux> { + fn request_stream(&self, input: Payload) -> Flux> { let sid = self.seq.next(); - let tx = self.tx.clone(); + let mut tx = self.tx.clone(); // register handler - let (sender, receiver) = new_tx_rx::>(); - let handlers = Arc::clone(&self.get_handler(sid)); + let (sender, receiver) = mpsc::channel::>(32); + let handlers = self.handlers.clone(); let splitter = self.splitter.clone(); - self.rt.spawn(async move { - { - let mut map = handlers.lock().await; - (*map).insert(sid, Handler::ReqRS(sender)); - } + runtime::spawn(async move { + handlers.insert(sid, Handler::ReqRS(sender)); match splitter { Some(sp) => { let mut cuts: usize = 0; @@ -854,7 +794,7 @@ where .build() }; // send frame - if let Err(e) = tx.unbounded_send(sending) { + if let Err(e) = tx.send(sending).await { error!("send request_stream failed: {}", e); return; } @@ -875,7 +815,7 @@ where .build() }; // send frame - if let Err(e) = tx.unbounded_send(sending) { + if let Err(e) = tx.send(sending).await { error!("send request_stream failed: {}", e); } } @@ -883,7 +823,7 @@ where let sending = frame::RequestStream::builder(sid, 0) .set_all(input.split()) .build(); - if let Err(e) = tx.unbounded_send(sending) { + if let Err(e) = tx.send(sending).await { error!("send request_stream failed: {}", e); } } @@ -892,30 +832,26 @@ where Box::pin(receiver) } - fn request_channel( - &self, - mut reqs: Flux>, - ) -> Flux> { + fn request_channel(&self, mut reqs: Flux>) -> Flux> { let sid = self.seq.next(); - let tx = self.tx.clone(); + let mut tx = self.tx.clone(); // register handler - let (sender, receiver) = new_tx_rx::>(); - let handlers = Arc::clone(&self.get_handler(sid)); + let (sender, receiver) = mpsc::channel::>(32); + let handlers = self.handlers.clone(); let splitter = self.splitter.clone(); - self.rt.spawn(async move { - { - let mut map = handlers.lock().await; - (*map).insert(sid, Handler::ReqRC(sender)); - } + runtime::spawn(async move { + handlers.insert(sid, Handler::ReqRC(sender)); let mut first = true; while let Some(next) = reqs.next().await { match next { Ok(it) => { if first { first = false; - Self::try_send_channel(&splitter, &tx, sid, it, Frame::FLAG_NEXT) + Self::try_send_channel(&splitter, &mut tx, sid, it, Frame::FLAG_NEXT) + .await } else { - Self::try_send_payload(&splitter, &tx, sid, it, Frame::FLAG_NEXT) + Self::try_send_payload(&splitter, &mut tx, sid, it, Frame::FLAG_NEXT) + .await } } Err(e) => { @@ -923,14 +859,14 @@ where .set_code(error::ERR_APPLICATION) .set_data(Bytes::from(format!("{}", e))) .build(); - if let Err(e) = tx.unbounded_send(sending) { + if let Err(e) = tx.send(sending).await { error!("send REQUEST_CHANNEL failed: {}", e); } } }; } let sending = frame::Payload::builder(sid, Frame::FLAG_COMPLETE).build(); - if let Err(e) = tx.unbounded_send(sending) { + if let Err(e) = tx.send(sending).await { error!("complete REQUEST_CHANNEL failed: {}", e); } }); @@ -971,19 +907,17 @@ impl RSocket for Responder { (*inner).fire_and_forget(req) } - fn request_response(&self, req: Payload) -> Mono> { + fn request_response(&self, req: Payload) -> Mono> { let inner = self.inner.read().unwrap(); (*inner).request_response(req) } - fn request_stream(&self, req: Payload) -> Flux> { + fn request_stream(&self, req: Payload) -> Flux> { let inner = self.inner.read().unwrap(); (*inner).request_stream(req) } - fn request_channel( - &self, - reqs: Flux>, - ) -> Flux> { + + fn request_channel(&self, reqs: Flux>) -> Flux> { let inner = self.inner.read().unwrap(); (*inner).request_channel(reqs) } diff --git a/rsocket/src/transport/spi.rs b/rsocket/src/transport/spi.rs index b929c15..6778277 100644 --- a/rsocket/src/transport/spi.rs +++ b/rsocket/src/transport/spi.rs @@ -1,51 +1,67 @@ -use crate::error::RSocketError; use crate::frame::Frame; use crate::payload::SetupPayload; use crate::spi::{ClientResponder, RSocket, ServerResponder}; +use crate::{Error, Result}; +use async_trait::async_trait; use futures::channel::{mpsc, oneshot}; -use std::error::Error; +use futures::sink::Sink; +use futures::stream::Stream; use std::future::Future; +use std::marker::Unpin; use std::pin::Pin; -use std::result::Result; use std::sync::Arc; +use tokio::sync::Notify; -pub type Tx = mpsc::UnboundedSender; -pub type Rx = mpsc::UnboundedReceiver; - -pub type TxOnce = oneshot::Sender; -pub type RxOnce = oneshot::Receiver; +#[derive(Clone)] +pub(crate) enum Acceptor { + Simple(Arc), + Generate(Arc), +} -pub(crate) fn new_tx_rx_once() -> (TxOnce, RxOnce) { - oneshot::channel() +#[async_trait] +pub trait Reader { + async fn read(&mut self) -> Option>; } -pub(crate) fn new_tx_rx() -> (Tx, Rx) { - mpsc::unbounded() +#[async_trait] +pub trait Writer { + async fn write(&mut self, frame: Frame) -> Result<()>; } -pub trait ClientTransport { - fn attach( +pub trait Connection { + fn split( self, - incoming: Tx, - sending: Rx, - connected: Option>>, + ) -> ( + Box, + Box, ); } -pub trait ServerTransport { +#[async_trait] +pub trait Transport { + type Conn: Connection + Send; + + async fn connect(self) -> Result; +} + +#[async_trait] +pub trait ServerTransportOld { type Item; - fn start( + async fn start( self, starter: Option>, - acceptor: impl Fn(Self::Item) + Send + Sync + 'static, - ) -> Pin>>>> + acceptor: Box Result<()> + Send + Sync>, + ) -> Result<()> where - Self::Item: ClientTransport + Sized; + Self::Item: Transport + Sized; } -#[derive(Clone)] -pub(crate) enum Acceptor { - Simple(Arc), - Generate(Arc), +#[async_trait] +pub trait ServerTransport { + type Item: Transport; + + async fn start(&mut self) -> Result<()>; + + async fn next(&mut self) -> Option>; } diff --git a/rsocket/src/utils.rs b/rsocket/src/utils.rs index b928d34..346e873 100644 --- a/rsocket/src/utils.rs +++ b/rsocket/src/utils.rs @@ -7,8 +7,6 @@ use std::result::Result; pub const DEFAULT_MIME_TYPE: &str = "application/binary"; -pub type RSocketResult = Result; - pub trait Writeable { fn write_to(&self, bf: &mut BytesMut); fn len(&self) -> usize; diff --git a/rsocket/src/x/factory.rs b/rsocket/src/x/factory.rs deleted file mode 100644 index 8926119..0000000 --- a/rsocket/src/x/factory.rs +++ /dev/null @@ -1,21 +0,0 @@ -use super::{Client, ClientBuilder, ServerBuilder}; -use crate::transport::{ClientTransport, ServerTransport}; - -pub struct RSocketFactory; - -impl RSocketFactory { - pub fn connect() -> ClientBuilder - where - T: Send + Sync + ClientTransport, - { - ClientBuilder::new() - } - - pub fn receive() -> ServerBuilder - where - T: Send + Sync + ServerTransport + 'static, - C: Send + Sync + ClientTransport + 'static, - { - ServerBuilder::new() - } -} diff --git a/rsocket/src/x/server.rs b/rsocket/src/x/server.rs deleted file mode 100644 index d6b28f9..0000000 --- a/rsocket/src/x/server.rs +++ /dev/null @@ -1,106 +0,0 @@ -use crate::error::RSocketError; -use crate::frame::{self, Frame}; -use crate::payload::SetupPayload; -use crate::runtime::{DefaultSpawner, Spawner}; -use crate::spi::{EmptyRSocket, RSocket, ServerResponder}; -use crate::transport::{self, Acceptor, ClientTransport, DuplexSocket, ServerTransport, Splitter}; -use futures::channel::{mpsc, oneshot}; -use std::error::Error; -use std::future::Future; -use std::net::SocketAddr; -use std::pin::Pin; -use std::result::Result; -use std::sync::Arc; - -pub struct ServerBuilder -where - T: Send + Sync + ServerTransport, - C: Send + Sync + ClientTransport, -{ - transport: Option, - on_setup: Option, - start_handler: Option>, - mtu: usize, -} - -impl ServerBuilder -where - T: Send + Sync + ServerTransport + 'static, - C: Send + Sync + ClientTransport + 'static, -{ - pub(crate) fn new() -> ServerBuilder { - ServerBuilder { - transport: None, - on_setup: None, - start_handler: None, - mtu: 0, - } - } - - pub fn fragment(mut self, mtu: usize) -> Self { - if mtu > 0 && mtu < transport::MIN_MTU { - panic!("invalid fragment mtu: at least {}!", transport::MIN_MTU) - } - self.mtu = mtu; - self - } - - pub fn acceptor(mut self, handler: ServerResponder) -> Self { - self.on_setup = Some(handler); - self - } - - pub fn on_start(mut self, hanlder: Box) -> Self { - self.start_handler = Some(hanlder); - self - } - - pub fn transport(mut self, transport: T) -> Self { - self.transport = Some(transport); - self - } - - pub async fn serve(self) -> Result<(), Box> { - self.serve_with_runtime(DefaultSpawner).await - } - - pub async fn serve_with_runtime(mut self, rt: R) -> Result<(), Box> - where - R: Send + Sync + Copy + Spawner + 'static, - { - let tp = self.transport.take().expect("missing transport"); - let starter = self.start_handler; - let acceptor = match self.on_setup { - Some(v) => Some(Acceptor::Generate(Arc::new(v))), - None => None, - }; - - let mtu = self.mtu; - - tp.start(starter, move |tp| { - let (rcv_tx, rcv_rx) = mpsc::unbounded::(); - let (snd_tx, snd_rx) = mpsc::unbounded::(); - tp.attach(rcv_tx, snd_rx, None); - let acceptor = acceptor.clone(); - - rt.spawn(async move { - let splitter = if mtu == 0 { - None - } else { - Some(Splitter::new(mtu)) - }; - let ds = DuplexSocket::new(rt, 0, snd_tx, splitter).await; - ds.event_loop(acceptor, rcv_rx).await; - }); - }) - .await - } -} - -#[inline] -fn on_setup_noop( - _setup: SetupPayload, - _socket: Box, -) -> Result, Box> { - Ok(Box::new(EmptyRSocket)) -} From 8e79980405a7c43eebd8ce35e626b8835d1d268a Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Fri, 6 Nov 2020 15:22:46 +0800 Subject: [PATCH 25/70] chore: use gh actions instead of travis (#22) --- .github/workflows/rust.yml | 22 ++++++++++++++++++++++ .travis.yml | 6 ------ 2 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/rust.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 0000000..3c13d1b --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,22 @@ +name: Rust + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Build + run: cargo build --verbose + - name: Run tests + run: cargo test --verbose diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index de5f0d4..0000000 --- a/.travis.yml +++ /dev/null @@ -1,6 +0,0 @@ -language: rust -rust: - - stable -script: - - cargo build --verbose --all - - cargo test -- --nocapture From 0cd69bac272e663d7d70d50f0b12d524f704b5a9 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Sun, 8 Nov 2020 19:03:26 +0800 Subject: [PATCH 26/70] refactor: use thiserror & anyhow as error struct (#20) Fix #18 --- examples/proxy.rs | 5 +- justfile | 10 +- rsocket-messaging/src/misc.rs | 18 +-- rsocket-messaging/src/requester.rs | 8 +- rsocket-transport-tcp/src/client/tcp.rs | 4 +- rsocket-transport-tcp/src/client/uds.rs | 4 +- rsocket-transport-tcp/src/connection/tcp.rs | 6 +- rsocket-transport-tcp/src/connection/uds.rs | 6 +- rsocket-transport-tcp/src/server/tcp.rs | 8 +- rsocket-transport-tcp/src/server/uds.rs | 6 +- rsocket-transport-wasm/src/client.rs | 9 +- rsocket-transport-wasm/src/connection.rs | 4 +- rsocket-transport-websocket/src/client.rs | 6 +- rsocket-transport-websocket/src/connection.rs | 5 +- rsocket-transport-websocket/src/server.rs | 6 +- rsocket/Cargo.toml | 3 +- rsocket/src/error.rs | 120 ++++++++---------- rsocket/src/extension/composite.rs | 19 ++- rsocket/src/extension/routing.rs | 4 +- rsocket/src/frame/mod.rs | 6 +- rsocket/src/frame/utils.rs | 4 +- rsocket/src/lib.rs | 2 +- rsocket/src/spi.rs | 14 +- rsocket/src/transport/misc.rs | 6 +- rsocket/src/transport/socket.rs | 14 +- 25 files changed, 142 insertions(+), 155 deletions(-) diff --git a/examples/proxy.rs b/examples/proxy.rs index e4d79dd..bffb1ff 100644 --- a/examples/proxy.rs +++ b/examples/proxy.rs @@ -4,10 +4,11 @@ extern crate log; use futures::executor::block_on; use rsocket_rust::prelude::*; use rsocket_rust_transport_tcp::*; -use std::error::Error; + +type Result = rsocket_rust::Result; #[tokio::main] -async fn main() -> Result<(), Box> { +async fn main() -> Result<()> { env_logger::builder().format_timestamp_millis().init(); RSocketFactory::receive() diff --git a/justfile b/justfile index 5d883f0..43532ae 100644 --- a/justfile +++ b/justfile @@ -2,12 +2,14 @@ alias b := bench alias e := echo build: - @cargo build + @cargo build test: - @cargo test -- --nocapture + @cargo test -- --nocapture lint: - @cargo clippy + @cargo clippy +fmt: + @cargo fmt echo: - @RUST_LOG=release cargo run --release --example echo -- serve tcp://127.0.0.1:7878 + @RUST_LOG=release cargo run --release --example echo -- serve tcp://127.0.0.1:7878 bench: @RUST_LOG=info cargo run --release --example qps -- -c 1000000 -s 1024 tcp://127.0.0.1:7878 diff --git a/rsocket-messaging/src/misc.rs b/rsocket-messaging/src/misc.rs index 18f9c44..adc807b 100644 --- a/rsocket-messaging/src/misc.rs +++ b/rsocket-messaging/src/misc.rs @@ -1,13 +1,13 @@ +use rsocket_rust::Result; use serde::{de::DeserializeOwned, Serialize}; -use std::error::Error; pub trait SerDe { - fn marshal(&self, data: &T) -> Result, Box> + fn marshal(&self, data: &T) -> Result> where Self: Sized, T: Sized + Serialize; - fn unmarshal(&self, raw: &[u8]) -> Result> + fn unmarshal(&self, raw: &[u8]) -> Result where Self: Sized, T: Sized + DeserializeOwned; @@ -17,14 +17,14 @@ pub trait SerDe { struct JsonSerDe {} impl SerDe for JsonSerDe { - fn marshal(&self, data: &T) -> Result, Box> + fn marshal(&self, data: &T) -> Result> where T: Sized + Serialize, { Ok(serde_json::to_vec(data)?) } - fn unmarshal(&self, raw: &[u8]) -> Result> + fn unmarshal(&self, raw: &[u8]) -> Result where T: Sized + DeserializeOwned, { @@ -43,14 +43,14 @@ pub fn cbor() -> impl SerDe { struct CborSerDe {} impl SerDe for CborSerDe { - fn marshal(&self, data: &T) -> Result, Box> + fn marshal(&self, data: &T) -> Result> where T: Sized + Serialize, { Ok(serde_cbor::to_vec(data)?) } - fn unmarshal(&self, raw: &[u8]) -> Result> + fn unmarshal(&self, raw: &[u8]) -> Result where T: Sized + DeserializeOwned, { @@ -58,14 +58,14 @@ impl SerDe for CborSerDe { } } -pub(crate) fn marshal(ser: impl SerDe, data: &T) -> Result, Box> +pub(crate) fn marshal(ser: impl SerDe, data: &T) -> Result> where T: Sized + Serialize, { ser.marshal(data) } -pub(crate) fn unmarshal(de: impl SerDe, raw: &[u8]) -> Result> +pub(crate) fn unmarshal(de: impl SerDe, raw: &[u8]) -> Result where T: Sized + DeserializeOwned, { diff --git a/rsocket-messaging/src/requester.rs b/rsocket-messaging/src/requester.rs index ee9ce78..93dbad4 100644 --- a/rsocket-messaging/src/requester.rs +++ b/rsocket-messaging/src/requester.rs @@ -3,7 +3,7 @@ use bytes::{Bytes, BytesMut}; use rsocket_rust::extension::{CompositeMetadata, MimeType, RoutingMetadata}; use rsocket_rust::prelude::*; use rsocket_rust::utils::Writeable; -use rsocket_rust::Result; +use rsocket_rust::{error::RSocketError, Result}; use rsocket_rust_transport_tcp::TcpClientTransport; use rsocket_rust_transport_websocket::WebsocketClientTransport; use serde::{de::DeserializeOwned, Serialize}; @@ -176,7 +176,7 @@ impl RequesterBuilder { let requester = Requester::from(rsocket); Ok(requester) } - None => Err("Missing transport!".into()), + None => Err(RSocketError::WithDescription("Missing transport!".into()).into()), } } } @@ -368,7 +368,7 @@ where match *mime_type { MimeType::APPLICATION_JSON => Ok(Some(unmarshal(misc::json(), &raw.as_ref())?)), MimeType::APPLICATION_CBOR => Ok(Some(unmarshal(misc::cbor(), &raw.as_ref())?)), - _ => Err("unsupported mime type!".into()), + _ => Err(RSocketError::WithDescription("unsupported mime type!".into()).into()), } } @@ -380,6 +380,6 @@ where match *mime_type { MimeType::APPLICATION_JSON => marshal(misc::json(), data), MimeType::APPLICATION_CBOR => marshal(misc::cbor(), data), - _ => Err("unsupported mime type!".into()), + _ => Err(RSocketError::WithDescription("unsupported mime type!".into()).into()), } } diff --git a/rsocket-transport-tcp/src/client/tcp.rs b/rsocket-transport-tcp/src/client/tcp.rs index d9c4af6..4d3e0b0 100644 --- a/rsocket-transport-tcp/src/client/tcp.rs +++ b/rsocket-transport-tcp/src/client/tcp.rs @@ -1,6 +1,6 @@ use crate::{connection::TcpConnection, misc::parse_tcp_addr}; use async_trait::async_trait; -use rsocket_rust::{transport::Transport, Result}; +use rsocket_rust::{error::RSocketError, transport::Transport, Result}; use std::net::SocketAddr; use tokio::net::TcpStream; @@ -24,7 +24,7 @@ impl Transport for TcpClientTransport { Connector::Direct(socket) => Ok(TcpConnection::from(socket)), Connector::Lazy(addr) => match TcpStream::connect(addr).await { Ok(stream) => Ok(TcpConnection::from(stream)), - Err(e) => Err(Box::new(e)), + Err(e) => Err(RSocketError::IO(e).into()), }, } } diff --git a/rsocket-transport-tcp/src/client/uds.rs b/rsocket-transport-tcp/src/client/uds.rs index 91779fe..749bf8f 100644 --- a/rsocket-transport-tcp/src/client/uds.rs +++ b/rsocket-transport-tcp/src/client/uds.rs @@ -1,7 +1,7 @@ use crate::connection::UnixConnection; use crate::misc::parse_uds_addr; use async_trait::async_trait; -use rsocket_rust::{transport::Transport, Result}; +use rsocket_rust::{error::RSocketError, transport::Transport, Result}; use tokio::net::UnixStream; #[derive(Debug)] @@ -24,7 +24,7 @@ impl Transport for UnixClientTransport { Connector::Direct(socket) => Ok(UnixConnection::from(socket)), Connector::Lazy(addr) => match UnixStream::connect(addr).await { Ok(stream) => Ok(UnixConnection::from(stream)), - Err(e) => Err(Box::new(e)), + Err(e) => Err(RSocketError::IO(e).into()), }, } } diff --git a/rsocket-transport-tcp/src/connection/tcp.rs b/rsocket-transport-tcp/src/connection/tcp.rs index 9d2f81e..8813d51 100644 --- a/rsocket-transport-tcp/src/connection/tcp.rs +++ b/rsocket-transport-tcp/src/connection/tcp.rs @@ -4,7 +4,7 @@ use futures::stream::{SplitSink, SplitStream}; use futures::{SinkExt, StreamExt}; use rsocket_rust::frame::Frame; use rsocket_rust::transport::{Connection, Reader, Writer}; -use rsocket_rust::Result; +use rsocket_rust::{error::RSocketError, Result}; use tokio::net::TcpStream; use tokio_util::codec::Framed; @@ -26,7 +26,7 @@ impl Writer for InnerWriter { async fn write(&mut self, frame: Frame) -> Result<()> { match self.sink.send(frame).await { Ok(()) => Ok(()), - Err(e) => Err(Box::new(e)), + Err(e) => Err(RSocketError::IO(e).into()), } } } @@ -36,7 +36,7 @@ impl Reader for InnerReader { async fn read(&mut self) -> Option> { match self.stream.next().await { Some(Ok(frame)) => Some(Ok(frame)), - Some(Err(e)) => Some(Err(Box::new(e))), + Some(Err(e)) => Some(Err(RSocketError::IO(e).into())), None => None, } } diff --git a/rsocket-transport-tcp/src/connection/uds.rs b/rsocket-transport-tcp/src/connection/uds.rs index db14804..b32c3cf 100644 --- a/rsocket-transport-tcp/src/connection/uds.rs +++ b/rsocket-transport-tcp/src/connection/uds.rs @@ -4,7 +4,7 @@ use futures::stream::{SplitSink, SplitStream}; use futures::{SinkExt, StreamExt}; use rsocket_rust::frame::Frame; use rsocket_rust::transport::{Connection, Reader, Writer}; -use rsocket_rust::Result; +use rsocket_rust::{error::RSocketError, Result}; use tokio::net::UnixStream; use tokio_util::codec::Framed; @@ -41,7 +41,7 @@ impl Writer for InnerWriter { async fn write(&mut self, frame: Frame) -> Result<()> { match self.sink.send(frame).await { Ok(()) => Ok(()), - Err(e) => Err(Box::new(e)), + Err(e) => Err(RSocketError::IO(e).into()), } } } @@ -51,7 +51,7 @@ impl Reader for InnerReader { async fn read(&mut self) -> Option> { match self.stream.next().await { Some(Ok(frame)) => Some(Ok(frame)), - Some(Err(e)) => Some(Err(Box::new(e))), + Some(Err(e)) => Some(Err(RSocketError::IO(e).into())), None => None, } } diff --git a/rsocket-transport-tcp/src/server/tcp.rs b/rsocket-transport-tcp/src/server/tcp.rs index 562ed5e..e15e5cf 100644 --- a/rsocket-transport-tcp/src/server/tcp.rs +++ b/rsocket-transport-tcp/src/server/tcp.rs @@ -1,6 +1,6 @@ use crate::{client::TcpClientTransport, misc::parse_tcp_addr}; use async_trait::async_trait; -use rsocket_rust::{transport::ServerTransport, Result}; +use rsocket_rust::{error::RSocketError, transport::ServerTransport, Result}; use std::net::SocketAddr; use tokio::net::TcpListener; @@ -33,7 +33,7 @@ impl ServerTransport for TcpServerTransport { debug!("listening on: {}", &self.addr); Ok(()) } - Err(e) => Err(Box::new(e)), + Err(e) => Err(RSocketError::IO(e).into()), } } @@ -44,9 +44,9 @@ impl ServerTransport for TcpServerTransport { let tp = TcpClientTransport::from(socket); Some(Ok(tp)) } - Err(e) => Some(Err(Box::new(e))), + Err(e) => Some(Err(RSocketError::IO(e).into())), }, - None => Some(Err("err".into())), + None => None, } } } diff --git a/rsocket-transport-tcp/src/server/uds.rs b/rsocket-transport-tcp/src/server/uds.rs index b509a53..a2e1249 100644 --- a/rsocket-transport-tcp/src/server/uds.rs +++ b/rsocket-transport-tcp/src/server/uds.rs @@ -1,7 +1,7 @@ use crate::client::UnixClientTransport; use crate::misc::parse_uds_addr; use async_trait::async_trait; -use rsocket_rust::{transport::ServerTransport, Result}; +use rsocket_rust::{error::RSocketError, transport::ServerTransport, Result}; use tokio::net::UnixListener; #[derive(Debug)] @@ -33,7 +33,7 @@ impl ServerTransport for UnixServerTransport { debug!("listening on: {}", &self.addr); Ok(()) } - Err(e) => Err(Box::new(e)), + Err(e) => Err(RSocketError::IO(e).into()), } } @@ -41,7 +41,7 @@ impl ServerTransport for UnixServerTransport { match self.listener.as_mut() { Some(listener) => match listener.accept().await { Ok((socket, _)) => Some(Ok(UnixClientTransport::from(socket))), - Err(e) => Some(Err(Box::new(e))), + Err(e) => Some(Err(RSocketError::IO(e).into())), }, None => None, } diff --git a/rsocket-transport-wasm/src/client.rs b/rsocket-transport-wasm/src/client.rs index f2e2a10..45a6c06 100644 --- a/rsocket-transport-wasm/src/client.rs +++ b/rsocket-transport-wasm/src/client.rs @@ -7,13 +7,12 @@ use js_sys::{ArrayBuffer, Uint8Array}; use rsocket_rust::frame::Frame; use rsocket_rust::transport::Transport; use rsocket_rust::utils::Writeable; -use rsocket_rust::Result; +use rsocket_rust::{error::RSocketError, Result}; use std::cell::RefCell; use std::future::Future; use std::rc::Rc; use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; -use wasm_bindgen_futures; use web_sys::{ErrorEvent, Event, FileReader, MessageEvent, ProgressEvent, WebSocket}; macro_rules! console_log { @@ -129,10 +128,12 @@ impl Transport for WebsocketClientTransport { ws.send_with_u8_array(&raw[..]) .expect("write data into websocket failed."); } - console_log!("***** attch end *****"); } Err(e) => { - connected.send(Err(e.as_string().unwrap().into())).unwrap(); + let msg = e.as_string().unwrap(); + connected + .send(Err(RSocketError::WithDescription(msg).into())) + .unwrap(); } } }); diff --git a/rsocket-transport-wasm/src/connection.rs b/rsocket-transport-wasm/src/connection.rs index 9a54739..0a1aa33 100644 --- a/rsocket-transport-wasm/src/connection.rs +++ b/rsocket-transport-wasm/src/connection.rs @@ -2,7 +2,7 @@ use async_trait::async_trait; use futures_channel::mpsc; use futures_util::{SinkExt, StreamExt}; use rsocket_rust::transport::{Connection, Reader, Writer}; -use rsocket_rust::{frame::Frame, Result}; +use rsocket_rust::{error::RSocketError, frame::Frame, Result}; #[derive(Debug)] pub struct WebsocketConnection { @@ -29,7 +29,7 @@ impl Writer for InnerWriter { async fn write(&mut self, frame: Frame) -> Result<()> { match self.tx.send(frame).await { Ok(()) => Ok(()), - Err(e) => Err(Box::new(e)), + Err(e) => Err(RSocketError::Other(e.into()).into()), } } } diff --git a/rsocket-transport-websocket/src/client.rs b/rsocket-transport-websocket/src/client.rs index 42fced4..ead122d 100644 --- a/rsocket-transport-websocket/src/client.rs +++ b/rsocket-transport-websocket/src/client.rs @@ -1,6 +1,6 @@ use super::connection::WebsocketConnection; use async_trait::async_trait; -use rsocket_rust::{transport::Transport, Result}; +use rsocket_rust::{error::RSocketError, transport::Transport, Result}; use std::net::SocketAddr; use tokio::net::TcpStream; use tokio_tungstenite::{accept_async, connect_async}; @@ -31,11 +31,11 @@ impl Transport for WebsocketClientTransport { match self.connector { Connector::Direct(stream) => match accept_async(stream).await { Ok(ws) => Ok(WebsocketConnection::new(ws)), - Err(e) => Err(Box::new(e)), + Err(e) => Err(RSocketError::Other(e.into()).into()), }, Connector::Lazy(u) => match connect_async(u).await { Ok((stream, _)) => Ok(WebsocketConnection::new(stream)), - Err(e) => Err(Box::new(e)), + Err(e) => Err(RSocketError::Other(e.into()).into()), }, } } diff --git a/rsocket-transport-websocket/src/connection.rs b/rsocket-transport-websocket/src/connection.rs index 028bf74..503ac78 100644 --- a/rsocket-transport-websocket/src/connection.rs +++ b/rsocket-transport-websocket/src/connection.rs @@ -3,6 +3,7 @@ use bytes::{BufMut, BytesMut}; use futures::stream::{SplitSink, SplitStream}; use futures::{SinkExt, StreamExt}; use rsocket_rust::{ + error::RSocketError, frame::Frame, transport::{Connection, Reader, Writer}, utils::Writeable, @@ -53,7 +54,7 @@ impl Writer for InnerWriter { let msg = Message::binary(bf.to_vec()); match self.sink.send(msg).await { Ok(()) => Ok(()), - Err(e) => Err(Box::new(e)), + Err(e) => Err(RSocketError::Other(e.into()).into()), } } } @@ -71,7 +72,7 @@ impl Reader for InnerReader { Err(e) => Some(Err(e)), } } - Some(Err(e)) => Some(Err(Box::new(e))), + Some(Err(e)) => Some(Err(RSocketError::Other(e.into()).into())), None => None, } } diff --git a/rsocket-transport-websocket/src/server.rs b/rsocket-transport-websocket/src/server.rs index edec38a..1235300 100644 --- a/rsocket-transport-websocket/src/server.rs +++ b/rsocket-transport-websocket/src/server.rs @@ -1,6 +1,6 @@ use super::client::WebsocketClientTransport; use async_trait::async_trait; -use rsocket_rust::{transport::ServerTransport, Result}; +use rsocket_rust::{error::RSocketError, transport::ServerTransport, Result}; use std::net::SocketAddr; use tokio::net::TcpListener; @@ -26,7 +26,7 @@ impl ServerTransport for WebsocketServerTransport { self.listener = Some(listener); Ok(()) } - Err(e) => Err(Box::new(e)), + Err(e) => Err(RSocketError::IO(e).into()), } } @@ -34,7 +34,7 @@ impl ServerTransport for WebsocketServerTransport { match self.listener.as_mut() { Some(listener) => match listener.accept().await { Ok((socket, _)) => Some(Ok(WebsocketClientTransport::from(socket))), - Err(e) => Some(Err(Box::new(e))), + Err(e) => Some(Err(RSocketError::Other(e.into()).into())), }, None => None, } diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index 77b92d3..3a4d573 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -16,6 +16,8 @@ futures = "0.3.5" lazy_static = "1.4.0" async-trait = "0.1.40" dashmap = "3.11.10" +thiserror = "1.0.20" +anyhow = "1.0.32" [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen-futures = "0.4.18" @@ -28,4 +30,3 @@ features = [ "rt-core", "rt-threaded", "sync", "stream" ] [features] default = [] frame = [] -wasm = [] \ No newline at end of file diff --git a/rsocket/src/error.rs b/rsocket/src/error.rs index 7d51ee9..3aaf645 100644 --- a/rsocket/src/error.rs +++ b/rsocket/src/error.rs @@ -1,6 +1,6 @@ -use std::error::Error as StdError; use std::fmt; use std::io; +use thiserror::Error; pub const ERR_INVALID_SETUP: u32 = 0x0000_0001; pub const ERR_UNSUPPORTED_SETUP: u32 = 0x0000_0002; @@ -13,78 +13,58 @@ pub const ERR_REJECTED: u32 = 0x0000_0202; pub const ERR_CANCELED: u32 = 0x0000_0203; pub const ERR_INVALID: u32 = 0x0000_0204; -#[derive(Debug)] -pub enum ErrorKind { - Internal(u32, String), - WithDescription(String), - IO(io::Error), - Cancelled(), - LengthTooShort(usize), - InComplete, -} - -#[derive(Debug)] -pub struct RSocketError { - kind: ErrorKind, -} - -impl StdError for RSocketError {} +#[derive(Error, Debug)] +pub enum RSocketError { + // Protocol errors: + #[error("INVALID_SETUP: {0}")] + InvalidSetup(String), + #[error("UNSUPPORTED_SETUP: {0}")] + UnsupportedSetup(String), + #[error("REJECTED_SETUP: {0}")] + RejectedSetup(String), + #[error("REJECTED_SETUP: {0}")] + RejectedResume(String), + #[error("CONNECTION_ERROR: {0}")] + ConnectionException(String), + #[error("CONNECTION_CLOSE: {0}")] + ConnectionClosed(String), + #[error("APPLICATION_ERROR: {0}")] + ApplicationException(String), + #[error("REJECTED: {0}")] + RequestRejected(String), + #[error("CANCELLED: {0}")] + RequestCancelled(String), + #[error("INVALID: {0}")] + RequestInvalid(String), + #[error("RESERVED({0}): {1}")] + Reserved(u32, String), -impl fmt::Display for RSocketError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match &self.kind { - ErrorKind::Internal(c, s) => write!(f, "ERROR({}): {}", translate(c), s), - ErrorKind::WithDescription(s) => write!(f, "{}", s), - ErrorKind::IO(e) => write!(f, "{}", e), - ErrorKind::Cancelled() => write!(f, "ERROR(CANCELLED)"), - ErrorKind::LengthTooShort(n) => write!(f, "ERROR(MINIMAL LENGTH {})", n), - ErrorKind::InComplete => write!(f, "INCOMPLETE"), - } - } -} - -impl From for RSocketError { - fn from(e: io::Error) -> RSocketError { - RSocketError { - kind: ErrorKind::IO(e), - } - } -} - -impl From for RSocketError { - fn from(kind: ErrorKind) -> RSocketError { - RSocketError { kind } - } -} -impl From for RSocketError { - fn from(e: String) -> RSocketError { - RSocketError { - kind: ErrorKind::WithDescription(e), - } - } + // Codec errors: + #[error("this frame is incomplete")] + InCompleteFrame, + // Custom errors: + #[error("{0}")] + WithDescription(String), + #[error(transparent)] + IO(#[from] io::Error), + #[error(transparent)] + Other(#[from] anyhow::Error), } -impl From<&'static str> for RSocketError { - fn from(e: &'static str) -> RSocketError { - RSocketError { - kind: ErrorKind::WithDescription(String::from(e)), +impl RSocketError { + pub(crate) fn must_new_from_code(code: u32, desc: String) -> Self { + match code { + ERR_APPLICATION => RSocketError::ApplicationException(desc), + ERR_INVALID_SETUP => RSocketError::InvalidSetup(desc), + ERR_UNSUPPORTED_SETUP => RSocketError::UnsupportedSetup(desc), + ERR_REJECT_SETUP => RSocketError::RejectedSetup(desc), + ERR_REJECT_RESUME => RSocketError::RejectedResume(desc), + ERR_CONN_FAILED => RSocketError::ConnectionException(desc), + ERR_CONN_CLOSED => RSocketError::ConnectionClosed(desc), + ERR_REJECTED => RSocketError::RequestRejected(desc), + ERR_CANCELED => RSocketError::RequestCancelled(desc), + ERR_INVALID => RSocketError::RequestInvalid(desc), + _ => RSocketError::Reserved(code, desc), } } } - -#[inline] -fn translate(code: &u32) -> &str { - match *code { - ERR_APPLICATION => "APPLICATION", - ERR_INVALID_SETUP => "INVALID_SETUP", - ERR_UNSUPPORTED_SETUP => "UNSUPPORTED_SETUP", - ERR_REJECT_SETUP => "REJECT_SETUP", - ERR_REJECT_RESUME => "REJECT_RESUME", - ERR_CONN_FAILED => "CONN_FAILED", - ERR_CONN_CLOSED => "CONN_CLOSED", - ERR_REJECTED => "REJECTED", - ERR_CANCELED => "CANCELED", - ERR_INVALID => "INVALID", - _ => "UNKNOWN", - } -} diff --git a/rsocket/src/extension/composite.rs b/rsocket/src/extension/composite.rs index 3b28d9b..365fd89 100644 --- a/rsocket/src/extension/composite.rs +++ b/rsocket/src/extension/composite.rs @@ -1,5 +1,5 @@ use super::mime::MimeType; -use crate::error::{ErrorKind, RSocketError}; +use crate::error::RSocketError; use crate::utils::{u24, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::collections::LinkedList; @@ -121,27 +121,32 @@ impl CompositeMetadata { Some(well) => well, None => { let err_str = format!("invalid Well-Known MIME type: identifier={:x}", n); - return Err(err_str.into()); + return Err(RSocketError::WithDescription(err_str).into()); } } } else { // Bad let mime_len = (first as usize) + 1; if bs.len() < mime_len { - return Err("broken composite metadata: empty MIME type!".into()); + return Err(RSocketError::WithDescription( + "broken composite metadata: empty MIME type!".into(), + ) + .into()); } let front = bs.split_to(mime_len); MimeType::Normal(String::from_utf8(front.to_vec()).unwrap()) }; if bs.len() < 3 { - return Err("broken composite metadata: not enough bytes!".into()); + return Err(RSocketError::WithDescription( + "broken composite metadata: not enough bytes!".into(), + ) + .into()); } let payload_size = u24::read_advance(bs).into(); if bs.len() < payload_size { - return Err( - format!("broken composite metadata: require {} bytes!", payload_size).into(), - ); + let desc = format!("broken composite metadata: require {} bytes!", payload_size); + return Err(RSocketError::WithDescription(desc).into()); } let metadata = bs.split_to(payload_size).freeze(); Ok(Some(CompositeMetadataEntry::new(mime_type, metadata))) diff --git a/rsocket/src/extension/routing.rs b/rsocket/src/extension/routing.rs index 56a4136..dd9e57b 100644 --- a/rsocket/src/extension/routing.rs +++ b/rsocket/src/extension/routing.rs @@ -1,4 +1,4 @@ -use crate::error::{ErrorKind, RSocketError}; +use crate::error::RSocketError; use crate::utils::Writeable; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -61,7 +61,7 @@ impl RoutingMetadata { } let size = bf.get_u8() as usize; if bf.len() < size { - return Err("require more bytes!".into()); + return Err(RSocketError::WithDescription("require more bytes!".into()).into()); } let tag = String::from_utf8(bf.split_to(size).to_vec()).unwrap(); Ok(Some(tag)) diff --git a/rsocket/src/frame/mod.rs b/rsocket/src/frame/mod.rs index 12f1b5d..0865524 100644 --- a/rsocket/src/frame/mod.rs +++ b/rsocket/src/frame/mod.rs @@ -1,4 +1,4 @@ -use crate::error::{ErrorKind, RSocketError}; +use crate::error::RSocketError; use crate::utils::Writeable; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -145,7 +145,7 @@ impl Frame { pub fn decode(b: &mut BytesMut) -> crate::Result { if b.len() < LEN_HEADER { - return Err(Box::new(RSocketError::from(ErrorKind::InComplete))); + return Err(RSocketError::InCompleteFrame.into()); } let sid = b.get_u32(); let n = b.get_u16(); @@ -167,7 +167,7 @@ impl Frame { Self::TYPE_ERROR => Error::decode(flag, b).map(Body::Error), Self::TYPE_RESUME_OK => ResumeOK::decode(flag, b).map(Body::ResumeOK), Self::TYPE_RESUME => Resume::decode(flag, b).map(Body::Resume), - _ => Err(format!("illegal frame type: {}", kind).into()), + typ => unreachable!("invalid frame type {}!", typ), }; body.map(|it| Frame::new(sid, it, flag)) } diff --git a/rsocket/src/frame/utils.rs b/rsocket/src/frame/utils.rs index 714ed70..bf44523 100644 --- a/rsocket/src/frame/utils.rs +++ b/rsocket/src/frame/utils.rs @@ -1,5 +1,5 @@ use super::Frame; -use crate::error::{ErrorKind, RSocketError}; +use crate::error::RSocketError; use crate::utils::{u24, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -39,5 +39,5 @@ pub(crate) fn write_payload(bf: &mut BytesMut, metadata: Option<&Bytes>, data: O } pub(crate) fn too_short(n: usize) -> crate::Result { - Err(Box::new(RSocketError::from(ErrorKind::LengthTooShort(n)))) + Err(RSocketError::InCompleteFrame.into()) } diff --git a/rsocket/src/lib.rs b/rsocket/src/lib.rs index d45f4ee..7bb8890 100644 --- a/rsocket/src/lib.rs +++ b/rsocket/src/lib.rs @@ -111,7 +111,7 @@ pub mod transport; pub mod utils; pub type Error = Box; -pub type Result = std::result::Result; +pub type Result = anyhow::Result; pub type PinBoxFuture = std::pin::Pin>>; pub use crate::core::{Client, ClientBuilder, ServerBuilder}; diff --git a/rsocket/src/spi.rs b/rsocket/src/spi.rs index 589d9d2..0ba7db5 100644 --- a/rsocket/src/spi.rs +++ b/rsocket/src/spi.rs @@ -1,4 +1,4 @@ -use crate::error::{self, ErrorKind, RSocketError}; +use crate::error::{self, RSocketError}; use crate::payload::{Payload, SetupPayload}; use crate::{runtime, Error, Result}; use futures::future; @@ -67,14 +67,6 @@ impl RSocket for EchoRSocket { pub(crate) struct EmptyRSocket; -impl EmptyRSocket { - #[inline] - fn must_failed(&self) -> Error { - let kind = ErrorKind::Internal(error::ERR_APPLICATION, String::from("NOT_IMPLEMENT")); - Box::new(RSocketError::from(kind)) - } -} - impl RSocket for EmptyRSocket { fn metadata_push(&self, _req: Payload) -> Mono<()> { Box::pin(async {}) @@ -85,7 +77,9 @@ impl RSocket for EmptyRSocket { } fn request_response(&self, _req: Payload) -> Mono> { - Box::pin(future::err(self.must_failed())) + Box::pin(future::err( + RSocketError::ApplicationException("NOT_IMPLEMENT".into()).into(), + )) } fn request_stream(&self, _req: Payload) -> Flux> { diff --git a/rsocket/src/transport/misc.rs b/rsocket/src/transport/misc.rs index 06b0fc9..76e2bf0 100644 --- a/rsocket/src/transport/misc.rs +++ b/rsocket/src/transport/misc.rs @@ -1,5 +1,5 @@ -use crate::error::{ErrorKind, RSocketError}; -use crate::frame::{self}; +use crate::error::RSocketError; +use crate::frame::Frame; use crate::payload::{Payload, SetupPayload}; use crate::spi::RSocket; use futures::future; @@ -50,7 +50,7 @@ impl Counter { } #[inline] -pub(crate) fn debug_frame(snd: bool, f: &frame::Frame) { +pub(crate) fn debug_frame(snd: bool, f: &Frame) { if snd { debug!("===> SND: {:?}", f); } else { diff --git a/rsocket/src/transport/socket.rs b/rsocket/src/transport/socket.rs index 86ce82e..2f5095c 100644 --- a/rsocket/src/transport/socket.rs +++ b/rsocket/src/transport/socket.rs @@ -1,7 +1,7 @@ use super::fragmentation::{Joiner, Splitter}; use super::misc::{debug_frame, Counter, StreamID}; use super::spi::*; -use crate::error::{self, ErrorKind, RSocketError}; +use crate::error::{self, RSocketError}; use crate::frame::{self, Body, Frame}; use crate::payload::{Payload, SetupPayload}; use crate::spi::{EmptyRSocket, Flux, Mono, RSocket}; @@ -254,9 +254,8 @@ impl DuplexSocket { self.joiners.remove(&sid); // pick handler if let Some((_, handler)) = self.handlers.remove(&sid) { - let kind = - ErrorKind::Internal(input.get_code(), input.get_data_utf8().unwrap().to_owned()); - let e: Result<_> = Err(Box::new(RSocketError::from(kind))); + let desc = input.get_data_utf8().unwrap().to_owned(); + let e: Result<_> = Err(RSocketError::must_new_from_code(input.get_code(), desc).into()); match handler { Handler::ReqRR(tx) => tx.send(e).expect("Send RR failed"), Handler::ResRR(_) => unreachable!(), @@ -270,7 +269,8 @@ impl DuplexSocket { async fn on_cancel(&mut self, sid: u32, _flag: u16) { self.joiners.remove(&sid); if let Some((_, handler)) = self.handlers.remove(&sid) { - let e: Result<_> = Err(Box::new(RSocketError::from(ErrorKind::Cancelled()))); + let e: Result<_> = + Err(RSocketError::RequestCancelled("request has been cancelled".into()).into()); match handler { Handler::ReqRR(sender) => { info!("REQUEST_RESPONSE {} cancelled!", sid); @@ -761,7 +761,9 @@ impl RSocket for DuplexSocket { Box::pin(async move { match rx.await { Ok(v) => v, - Err(_e) => Err("request_response failed".into()), + Err(_e) => { + Err(RSocketError::WithDescription("request_response failed".into()).into()) + } } }) } From 396653f5cf996120d8ac05a10cb7107778a090f6 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Sun, 8 Nov 2020 22:06:41 +0800 Subject: [PATCH 27/70] feat: support tokio v0.3.x (#23) --- README.md | 1 + examples/Cargo.toml | 8 ++++---- examples/qps.rs | 2 +- rsocket-messaging/Cargo.toml | 10 +++++----- rsocket-test/Cargo.toml | 12 ++++++------ rsocket-test/tests/test_clients.rs | 6 +++--- rsocket-transport-tcp/Cargo.toml | 12 ++++++------ rsocket-transport-wasm/Cargo.toml | 12 ++++++------ rsocket-transport-websocket/Cargo.toml | 14 +++++++------- rsocket/Cargo.toml | 14 +++++++------- rsocket/src/frame/error.rs | 2 +- rsocket/src/frame/keepalive.rs | 2 +- rsocket/src/frame/lease.rs | 2 +- rsocket/src/transport/socket.rs | 18 +++++++++--------- 14 files changed, 58 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index ce52ca5..5e839f9 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # rsocket-rust +![GitHub Workflow Status](https://github.com/rsocket/rsocket-rust/workflows/Rust/badge.svg) [![Build Status](https://travis-ci.com/rsocket/rsocket-rust.svg?branch=master)](https://travis-ci.com/rsocket/rsocket-rust) [![Crates.io](https://img.shields.io/crates/v/rsocket_rust)](https://crates.io/crates/rsocket_rust) [![Crates.io](https://img.shields.io/crates/d/rsocket_rust)](https://crates.io/crates/rsocket_rust) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 64df85b..da43620 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -7,10 +7,10 @@ publish = false [dev-dependencies] log = "0.4.11" -env_logger = "0.7.1" -futures = "0.3.5" +env_logger = "0.8.1" +futures = "0.3.7" clap = "2.33.3" -tokio-postgres = "0.5.5" +tokio-postgres = "0.6.0" redis = "0.17.0" [dev-dependencies.rsocket_rust] @@ -23,7 +23,7 @@ path = "../rsocket-transport-tcp" path = "../rsocket-transport-websocket" [dev-dependencies.tokio] -version = "0.2.22" +version = "0.3.3" default-features = false features = ["full"] diff --git a/examples/qps.rs b/examples/qps.rs index 2fbce66..e8abcf6 100644 --- a/examples/qps.rs +++ b/examples/qps.rs @@ -48,7 +48,7 @@ where } let current = counter.fetch_add(1, Ordering::SeqCst) + 1; if current >= count { - notify.notify(); + notify.notify_one(); } }); } diff --git a/rsocket-messaging/Cargo.toml b/rsocket-messaging/Cargo.toml index b17d917..430edc8 100644 --- a/rsocket-messaging/Cargo.toml +++ b/rsocket-messaging/Cargo.toml @@ -10,13 +10,13 @@ homepage = "https://github.com/rsocket/rsocket-rust" description = "Communicate with Spring RSocket Messaging." [dependencies] -futures = "0.3.5" -bytes = "0.5.6" -serde = "1.0.116" -serde_json = "1.0.57" +futures = "0.3.7" +bytes = "0.6.0" +serde = "1.0.117" +serde_json = "1.0.59" serde_cbor = "0.11.1" hex = "0.4.2" -url = "2.1.1" +url = "2.2.0" [dependencies.rsocket_rust] path = "../rsocket" diff --git a/rsocket-test/Cargo.toml b/rsocket-test/Cargo.toml index de7a312..2f71bac 100644 --- a/rsocket-test/Cargo.toml +++ b/rsocket-test/Cargo.toml @@ -7,13 +7,13 @@ publish = false [dev-dependencies] log = "0.4" -futures = "0.3.5" -env_logger = "0.7.1" -bytes = "0.5.6" +futures = "0.3.7" +env_logger = "0.8.1" +bytes = "0.6.0" hex = "0.4.2" rand = "0.7.3" -serde = "1.0.116" -serde_derive = "1.0.116" +serde = "1.0.117" +serde_derive = "1.0.117" [dev-dependencies.rsocket_rust] path = "../rsocket" @@ -29,6 +29,6 @@ path = "../rsocket-transport-websocket" path = "../rsocket-messaging" [dev-dependencies.tokio] -version = "0.2.22" +version = "0.3.3" default-features = false features = ["full"] diff --git a/rsocket-test/tests/test_clients.rs b/rsocket-test/tests/test_clients.rs index 216b33a..a262628 100644 --- a/rsocket-test/tests/test_clients.rs +++ b/rsocket-test/tests/test_clients.rs @@ -54,7 +54,7 @@ fn test_websocket() { sleep(Duration::from_millis(500)); - let mut client_runtime = Runtime::new().unwrap(); + let client_runtime = Runtime::new().unwrap(); client_runtime.block_on(async { let cli = RSocketFactory::connect() @@ -102,7 +102,7 @@ fn test_tcp() { sleep(Duration::from_millis(500)); - let mut client_runtime = Runtime::new().unwrap(); + let client_runtime = Runtime::new().unwrap(); client_runtime.block_on(async { let cli = RSocketFactory::connect() @@ -158,7 +158,7 @@ fn test_unix() { sleep(Duration::from_millis(500)); - let mut client_runtime = Runtime::new().unwrap(); + let client_runtime = Runtime::new().unwrap(); client_runtime.block_on(async { let cli = RSocketFactory::connect() diff --git a/rsocket-transport-tcp/Cargo.toml b/rsocket-transport-tcp/Cargo.toml index 5cf1c61..827cb00 100644 --- a/rsocket-transport-tcp/Cargo.toml +++ b/rsocket-transport-tcp/Cargo.toml @@ -11,20 +11,20 @@ description = "TCP RSocket transport implementation." [dependencies] log = "0.4.11" -futures = "0.3.5" -bytes = "0.5.6" -async-trait = "0.1.40" +futures = "0.3.7" +bytes = "0.6.0" +async-trait = "0.1.41" [dependencies.rsocket_rust] path = "../rsocket" features = ["frame"] [dependencies.tokio] -version = "0.2.22" +version = "0.3.3" default-features = false -features = [ "rt-core", "rt-threaded", "tcp", "uds", "sync", "dns", "stream", "io-util", "macros" ] +features = [ "rt", "rt-multi-thread", "net", "sync", "stream", "io-util", "macros" ] [dependencies.tokio-util] -version = "0.3.1" +version = "0.5.0" default-features = false features = ["codec"] diff --git a/rsocket-transport-wasm/Cargo.toml b/rsocket-transport-wasm/Cargo.toml index 52c7703..a3670f6 100644 --- a/rsocket-transport-wasm/Cargo.toml +++ b/rsocket-transport-wasm/Cargo.toml @@ -10,14 +10,14 @@ homepage = "https://github.com/rsocket/rsocket-rust" description = "WASM Websocket RSocket transport implementation." [dependencies] -bytes = "0.5.6" +bytes = "0.6.0" wasm-bindgen-futures = "0.4.18" -futures-channel = "0.3.5" -futures-util = "0.3.5" +futures-channel = "0.3.7" +futures-util = "0.3.7" js-sys = "0.3.45" -serde = "1.0.116" -serde_derive = "1.0.116" -async-trait = "0.1.40" +serde = "1.0.117" +serde_derive = "1.0.117" +async-trait = "0.1.41" [dependencies.rsocket_rust] path = "../rsocket" diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index 225c9e5..648f65f 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -11,17 +11,17 @@ description = "Websocket RSocket transport implementation." [dependencies] log = "0.4.11" -futures = "0.3.5" -bytes = "0.5.6" -url = "2.1.1" -tokio-tungstenite = "0.11.0" -async-trait = "0.1.40" +futures = "0.3.7" +bytes = "0.6.0" +url = "2.2.0" +tokio-tungstenite = "0.12.0" +async-trait = "0.1.41" [dependencies.rsocket_rust] path = "../rsocket" features = ["frame"] [dependencies.tokio] -version = "0.2.22" +version = "0.3.3" default-features = false -features = [ "rt-core", "rt-threaded", "tcp", "sync", "stream" ] +features = [ "rt", "rt-multi-thread", "net", "sync", "stream" ] diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index 3a4d573..ff75318 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -11,21 +11,21 @@ description = "rsocket-rust is an implementation of the RSocket protocol in Rust [dependencies] log = "0.4.11" -bytes = "0.5.6" -futures = "0.3.5" +bytes = "0.6.0" +futures = "0.3.7" lazy_static = "1.4.0" -async-trait = "0.1.40" +async-trait = "0.1.41" dashmap = "3.11.10" -thiserror = "1.0.20" -anyhow = "1.0.32" +thiserror = "1.0.22" +anyhow = "1.0.34" [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen-futures = "0.4.18" [dependencies.tokio] -version = "0.2.22" +version = "0.3.3" default-features = false -features = [ "rt-core", "rt-threaded", "sync", "stream" ] +features = [ "rt", "rt-multi-thread", "sync", "stream" ] [features] default = [] diff --git a/rsocket/src/frame/error.rs b/rsocket/src/frame/error.rs index e8cae2c..75427d8 100644 --- a/rsocket/src/frame/error.rs +++ b/rsocket/src/frame/error.rs @@ -50,7 +50,7 @@ impl Error { } else { let code = bf.get_u32(); let data: Option = if !bf.is_empty() { - Some(bf.to_bytes()) + Some(Bytes::from(bf.to_vec())) } else { None }; diff --git a/rsocket/src/frame/keepalive.rs b/rsocket/src/frame/keepalive.rs index 562794e..f5664e2 100644 --- a/rsocket/src/frame/keepalive.rs +++ b/rsocket/src/frame/keepalive.rs @@ -51,7 +51,7 @@ impl Keepalive { let data = if bf.is_empty() { None } else { - Some(bf.to_bytes()) + Some(Bytes::from(bf.to_vec())) }; Ok(Keepalive { last_received_position: position, diff --git a/rsocket/src/frame/lease.rs b/rsocket/src/frame/lease.rs index fc0fd48..c0891e2 100644 --- a/rsocket/src/frame/lease.rs +++ b/rsocket/src/frame/lease.rs @@ -58,7 +58,7 @@ impl Lease { let ttl = bf.get_u32(); let n = bf.get_u32(); let m = if flag & Frame::FLAG_METADATA != 0 { - Some(bf.to_bytes()) + Some(Bytes::from(bf.to_vec())) } else { None }; diff --git a/rsocket/src/transport/socket.rs b/rsocket/src/transport/socket.rs index 2f5095c..6a6cf33 100644 --- a/rsocket/src/transport/socket.rs +++ b/rsocket/src/transport/socket.rs @@ -259,8 +259,8 @@ impl DuplexSocket { match handler { Handler::ReqRR(tx) => tx.send(e).expect("Send RR failed"), Handler::ResRR(_) => unreachable!(), - Handler::ReqRS(mut tx) => tx.send(e).await.expect("Send RS failed"), - Handler::ReqRC(mut tx) => tx.send(e).await.expect("Send RC failed"), + Handler::ReqRS(tx) => tx.send(e).await.expect("Send RS failed"), + Handler::ReqRC(tx) => tx.send(e).await.expect("Send RC failed"), } } } @@ -368,7 +368,7 @@ impl DuplexSocket { #[inline] async fn on_request_response(&mut self, sid: u32, _flag: u16, input: Payload) { let responder = self.responder.clone(); - let mut canceller = self.canceller.clone(); + let canceller = self.canceller.clone(); let mut tx = self.tx.clone(); let splitter = self.splitter.clone(); let counter = Counter::new(2); @@ -441,8 +441,8 @@ impl DuplexSocket { #[inline] async fn on_request_channel(&self, sid: u32, flag: u16, first: Payload) { let responder = self.responder.clone(); - let mut tx = self.tx.clone(); - let (mut sender, receiver) = mpsc::channel::>(32); + let tx = self.tx.clone(); + let (sender, receiver) = mpsc::channel::>(32); sender.send(Ok(first)).await.expect("Send failed!"); self.register_handler(sid, Handler::ReqRC(sender)).await; runtime::spawn(async move { @@ -620,7 +620,7 @@ impl DuplexSocket { impl RSocket for DuplexSocket { fn metadata_push(&self, req: Payload) -> Mono<()> { let sid = self.seq.next(); - let mut tx = self.tx.clone(); + let tx = self.tx.clone(); Box::pin(async move { let (_d, m) = req.split(); let mut bu = frame::MetadataPush::builder(sid, 0); @@ -634,7 +634,7 @@ impl RSocket for DuplexSocket { } fn fire_and_forget(&self, req: Payload) -> Mono<()> { let sid = self.seq.next(); - let mut tx = self.tx.clone(); + let tx = self.tx.clone(); let splitter = self.splitter.clone(); Box::pin(async move { match splitter { @@ -696,7 +696,7 @@ impl RSocket for DuplexSocket { let (tx, rx) = oneshot::channel::>(); let sid = self.seq.next(); let handlers = self.handlers.clone(); - let mut sender = self.tx.clone(); + let sender = self.tx.clone(); let splitter = self.splitter.clone(); @@ -770,7 +770,7 @@ impl RSocket for DuplexSocket { fn request_stream(&self, input: Payload) -> Flux> { let sid = self.seq.next(); - let mut tx = self.tx.clone(); + let tx = self.tx.clone(); // register handler let (sender, receiver) = mpsc::channel::>(32); let handlers = self.handlers.clone(); From 06a22aba8be28c291a56fcdad90d894d750d6339 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Tue, 10 Nov 2020 11:08:27 +0800 Subject: [PATCH 28/70] fix: optimize bytes write action (#24) --- rsocket/src/extension/composite.rs | 4 ++-- rsocket/src/frame/error.rs | 8 ++++---- rsocket/src/frame/keepalive.rs | 8 ++++---- rsocket/src/frame/lease.rs | 8 ++++---- rsocket/src/frame/metadata_push.rs | 7 ++++--- rsocket/src/frame/request_channel.rs | 3 ++- rsocket/src/frame/request_n.rs | 3 ++- rsocket/src/frame/request_stream.rs | 3 ++- rsocket/src/frame/resume.rs | 10 +++++----- rsocket/src/frame/resume_ok.rs | 4 ++-- rsocket/src/frame/setup.rs | 23 ++++++++++++----------- rsocket/src/frame/utils.rs | 14 ++++++-------- 12 files changed, 49 insertions(+), 46 deletions(-) diff --git a/rsocket/src/extension/composite.rs b/rsocket/src/extension/composite.rs index 365fd89..712401e 100644 --- a/rsocket/src/extension/composite.rs +++ b/rsocket/src/extension/composite.rs @@ -191,13 +191,13 @@ impl Writeable for CompositeMetadataEntry { let mime_type_len = s.len() as u8; assert!(mime_type_len > 0, "invalid length of MimeType!"); bf.put_u8(mime_type_len - 1); - bf.put_slice(s.as_ref()); + bf.extend_from_slice(s.as_ref()); } }; let metadata_len = self.metadata.len(); u24::from(metadata_len).write_to(bf); if metadata_len > 0 { - bf.put(self.metadata.bytes()); + bf.extend_from_slice(&self.metadata); } } diff --git a/rsocket/src/frame/error.rs b/rsocket/src/frame/error.rs index 75427d8..ccc86b2 100644 --- a/rsocket/src/frame/error.rs +++ b/rsocket/src/frame/error.rs @@ -1,5 +1,5 @@ -use super::utils::too_short; use super::{Body, Frame}; +use crate::error::RSocketError; use crate::utils::Writeable; use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::fmt; @@ -46,11 +46,11 @@ impl ErrorBuilder { impl Error { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> crate::Result { if bf.len() < 4 { - too_short(4) + Err(RSocketError::InCompleteFrame.into()) } else { let code = bf.get_u32(); let data: Option = if !bf.is_empty() { - Some(Bytes::from(bf.to_vec())) + Some(bf.split().freeze()) } else { None }; @@ -85,7 +85,7 @@ impl Writeable for Error { fn write_to(&self, bf: &mut BytesMut) { bf.put_u32(self.code); match &self.data { - Some(v) => bf.put(v.bytes()), + Some(v) => bf.extend_from_slice(v), None => (), } } diff --git a/rsocket/src/frame/keepalive.rs b/rsocket/src/frame/keepalive.rs index f5664e2..074cf86 100644 --- a/rsocket/src/frame/keepalive.rs +++ b/rsocket/src/frame/keepalive.rs @@ -1,5 +1,5 @@ -use super::utils::too_short; use super::{Body, Frame}; +use crate::error::RSocketError; use crate::utils::Writeable; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -45,13 +45,13 @@ impl KeepaliveBuilder { impl Keepalive { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> crate::Result { if bf.len() < 8 { - return too_short(8); + return Err(RSocketError::InCompleteFrame.into()); } let position = bf.get_u64(); let data = if bf.is_empty() { None } else { - Some(Bytes::from(bf.to_vec())) + Some(bf.split().freeze()) }; Ok(Keepalive { last_received_position: position, @@ -83,7 +83,7 @@ impl Writeable for Keepalive { fn write_to(&self, bf: &mut BytesMut) { bf.put_u64(self.last_received_position); match &self.data { - Some(v) => bf.put(v.bytes()), + Some(v) => bf.extend_from_slice(v), None => (), } } diff --git a/rsocket/src/frame/lease.rs b/rsocket/src/frame/lease.rs index c0891e2..938969c 100644 --- a/rsocket/src/frame/lease.rs +++ b/rsocket/src/frame/lease.rs @@ -1,5 +1,5 @@ -use super::utils::too_short; use super::{Body, Frame}; +use crate::error::RSocketError; use crate::utils::Writeable; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -53,12 +53,12 @@ impl LeaseBuilder { impl Lease { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> crate::Result { if bf.len() < 8 { - return too_short(8); + return Err(RSocketError::InCompleteFrame.into()); } let ttl = bf.get_u32(); let n = bf.get_u32(); let m = if flag & Frame::FLAG_METADATA != 0 { - Some(Bytes::from(bf.to_vec())) + Some(bf.split().freeze()) } else { None }; @@ -94,7 +94,7 @@ impl Writeable for Lease { bf.put_u32(self.ttl); bf.put_u32(self.number_of_requests); match &self.metadata { - Some(v) => bf.put(v.bytes()), + Some(v) => bf.extend_from_slice(v), None => (), } } diff --git a/rsocket/src/frame/metadata_push.rs b/rsocket/src/frame/metadata_push.rs index 5db9aae..213845e 100644 --- a/rsocket/src/frame/metadata_push.rs +++ b/rsocket/src/frame/metadata_push.rs @@ -34,8 +34,9 @@ impl MetadataPushBuiler { impl MetadataPush { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> crate::Result { - let m = Bytes::from(bf.to_vec()); - Ok(MetadataPush { metadata: Some(m) }) + Ok(MetadataPush { + metadata: Some(bf.split().freeze()), + }) } pub fn builder(stream_id: u32, flag: u16) -> MetadataPushBuiler { @@ -57,7 +58,7 @@ impl MetadataPush { impl Writeable for MetadataPush { fn write_to(&self, bf: &mut BytesMut) { match &self.metadata { - Some(v) => bf.put(v.bytes()), + Some(v) => bf.extend_from_slice(v), None => (), } } diff --git a/rsocket/src/frame/request_channel.rs b/rsocket/src/frame/request_channel.rs index a652b1e..9c8a681 100644 --- a/rsocket/src/frame/request_channel.rs +++ b/rsocket/src/frame/request_channel.rs @@ -1,5 +1,6 @@ use super::utils; use super::{Body, Frame, REQUEST_MAX}; +use crate::error::RSocketError; use crate::utils::Writeable; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -68,7 +69,7 @@ impl RequestChannelBuilder { impl RequestChannel { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> crate::Result { if bf.len() < 4 { - utils::too_short(4) + Err(RSocketError::InCompleteFrame.into()) } else { let initial_request_n = bf.get_u32(); utils::read_payload(flag, bf).map(move |(metadata, data)| RequestChannel { diff --git a/rsocket/src/frame/request_n.rs b/rsocket/src/frame/request_n.rs index 989af66..1f6be4a 100644 --- a/rsocket/src/frame/request_n.rs +++ b/rsocket/src/frame/request_n.rs @@ -1,4 +1,5 @@ use super::{utils, Body, Frame, REQUEST_MAX}; +use crate::error::RSocketError; use crate::utils::Writeable; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -35,7 +36,7 @@ impl RequestNBuilder { impl RequestN { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> crate::Result { if bf.len() < 4 { - utils::too_short(4) + Err(RSocketError::InCompleteFrame.into()) } else { let n = bf.get_u32(); Ok(RequestN { n }) diff --git a/rsocket/src/frame/request_stream.rs b/rsocket/src/frame/request_stream.rs index b451df8..e0cb18d 100644 --- a/rsocket/src/frame/request_stream.rs +++ b/rsocket/src/frame/request_stream.rs @@ -1,4 +1,5 @@ use super::{utils, Body, Frame, REQUEST_MAX}; +use crate::error::RSocketError; use crate::utils::Writeable; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -55,7 +56,7 @@ impl RequestStreamBuilder { impl RequestStream { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> crate::Result { if bf.len() < 4 { - utils::too_short(4) + Err(RSocketError::InCompleteFrame.into()) } else { let initial_request_n = bf.get_u32(); utils::read_payload(flag, bf).map(move |(metadata, data)| RequestStream { diff --git a/rsocket/src/frame/resume.rs b/rsocket/src/frame/resume.rs index cf70a17..4fea1bc 100644 --- a/rsocket/src/frame/resume.rs +++ b/rsocket/src/frame/resume.rs @@ -1,5 +1,5 @@ -use super::utils::too_short; use super::{Body, Frame, Version}; +use crate::error::RSocketError; use crate::utils::Writeable; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -29,21 +29,21 @@ impl Resume { pub(crate) fn decode(flag: u16, b: &mut BytesMut) -> crate::Result { if b.len() < 6 { - return too_short(6); + return Err(RSocketError::InCompleteFrame.into()); } let major = b.get_u16(); let minor = b.get_u16(); let token_size = b.get_u16() as usize; let token = if token_size > 0 { if b.len() < token_size { - return too_short(token_size); + return Err(RSocketError::InCompleteFrame.into()); } Some(b.split_to(token_size).freeze()) } else { None }; if b.len() < 16 { - return too_short(16); + return Err(RSocketError::InCompleteFrame.into()); } let last_received_server_position = b.get_u64(); let first_available_client_position = b.get_u64(); @@ -114,7 +114,7 @@ impl Writeable for Resume { self.version.write_to(bf); if let Some(b) = self.get_token() { bf.put_u16(b.len() as u16); - bf.put(b.bytes()); + bf.extend_from_slice(b); } bf.put_u64(self.get_last_received_server_position()); bf.put_u64(self.get_first_available_client_position()); diff --git a/rsocket/src/frame/resume_ok.rs b/rsocket/src/frame/resume_ok.rs index aac2162..b541ff1 100644 --- a/rsocket/src/frame/resume_ok.rs +++ b/rsocket/src/frame/resume_ok.rs @@ -1,5 +1,5 @@ -use super::utils::too_short; use super::{Body, Frame}; +use crate::error::RSocketError; use crate::utils::Writeable; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -35,7 +35,7 @@ impl ResumeOKBuilder { impl ResumeOK { pub(crate) fn decode(flag: u16, bf: &mut BytesMut) -> crate::Result { if bf.len() < 8 { - too_short(8) + Err(RSocketError::InCompleteFrame.into()) } else { Ok(ResumeOK { position: bf.get_u64(), diff --git a/rsocket/src/frame/setup.rs b/rsocket/src/frame/setup.rs index f033506..f728a92 100644 --- a/rsocket/src/frame/setup.rs +++ b/rsocket/src/frame/setup.rs @@ -1,5 +1,6 @@ -use super::utils::{self, too_short}; +use super::utils; use super::{Body, Frame, Version}; +use crate::error::RSocketError; use crate::utils::{Writeable, DEFAULT_MIME_TYPE}; use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::time::Duration; @@ -26,7 +27,7 @@ impl Setup { pub(crate) fn decode(flag: u16, b: &mut BytesMut) -> crate::Result { // Check minimal length: version(4bytes) + keepalive(4bytes) + lifetime(4bytes) if b.len() < 12 { - return too_short(12); + return Err(RSocketError::InCompleteFrame.into()); } let major = b.get_u16(); let minor = b.get_u16(); @@ -34,32 +35,32 @@ impl Setup { let lifetime = b.get_u32(); let token: Option = if flag & Frame::FLAG_RESUME != 0 { if b.len() < 2 { - return too_short(2); + return Err(RSocketError::InCompleteFrame.into()); } let token_length = b.get_u16() as usize; if b.len() < token_length { - return too_short(token_length); + return Err(RSocketError::InCompleteFrame.into()); } Some(b.split_to(token_length).freeze()) } else { None }; if b.is_empty() { - return too_short(1); + return Err(RSocketError::InCompleteFrame.into()); } let mut mime_type_length: usize = b[0] as usize; b.advance(1); if b.len() < mime_type_length { - return too_short(mime_type_length); + return Err(RSocketError::InCompleteFrame.into()); } let mime_metadata = b.split_to(mime_type_length).freeze(); if b.is_empty() { - return too_short(1); + return Err(RSocketError::InCompleteFrame.into()); } mime_type_length = b[0] as usize; b.advance(1); if b.len() < mime_type_length { - return too_short(mime_type_length); + return Err(RSocketError::InCompleteFrame.into()); } let mime_data = b.split_to(mime_type_length).freeze(); let (metadata, data) = utils::read_payload(flag, b)?; @@ -143,12 +144,12 @@ impl Writeable for Setup { bf.put_u32(self.lifetime); if let Some(b) = &self.token { bf.put_u16(b.len() as u16); - bf.put(b.bytes()); + bf.extend_from_slice(b); } bf.put_u8(self.mime_metadata.len() as u8); - bf.put(self.mime_metadata.clone()); + bf.extend_from_slice(&self.mime_metadata); bf.put_u8(self.mime_data.len() as u8); - bf.put(self.mime_data.clone()); + bf.extend_from_slice(&self.mime_data); utils::write_payload(bf, self.get_metadata(), self.get_data()); } } diff --git a/rsocket/src/frame/utils.rs b/rsocket/src/frame/utils.rs index bf44523..badac2f 100644 --- a/rsocket/src/frame/utils.rs +++ b/rsocket/src/frame/utils.rs @@ -3,13 +3,14 @@ use crate::error::RSocketError; use crate::utils::{u24, Writeable}; use bytes::{Buf, BufMut, Bytes, BytesMut}; +#[inline] pub(crate) fn read_payload( flag: u16, bf: &mut BytesMut, ) -> crate::Result<(Option, Option)> { let m: Option = if flag & Frame::FLAG_METADATA != 0 { if bf.len() < 3 { - return too_short(3); + return Err(RSocketError::InCompleteFrame.into()); } let n = u24::read_advance(bf); Some(bf.split_to(n.into()).freeze()) @@ -19,7 +20,7 @@ pub(crate) fn read_payload( let d: Option = if bf.is_empty() { None } else { - Some(Bytes::from(bf.to_vec())) + Some(bf.split().freeze()) }; Ok((m, d)) } @@ -28,16 +29,13 @@ pub(crate) fn calculate_payload_length(metadata: Option<&Bytes>, data: Option<&B metadata.map(|v| 3 + v.len()).unwrap_or(0) + data.map(|v| v.len()).unwrap_or(0) } +#[inline] pub(crate) fn write_payload(bf: &mut BytesMut, metadata: Option<&Bytes>, data: Option<&Bytes>) { if let Some(v) = metadata { u24::from(v.len()).write_to(bf); - bf.put(v.clone()); + bf.extend_from_slice(v); } if let Some(v) = data { - bf.put(v.clone()) + bf.extend_from_slice(v); } } - -pub(crate) fn too_short(n: usize) -> crate::Result { - Err(RSocketError::InCompleteFrame.into()) -} From c67e96da721e3700f2d00d35ed420984cdba7925 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Tue, 10 Nov 2020 11:14:17 +0800 Subject: [PATCH 29/70] feat: implement client-side keepalive (#25) --- examples/cli.rs | 15 +++++++++--- examples/echo.rs | 3 +-- examples/proxy.rs | 3 +-- examples/qps.rs | 6 ++--- rsocket/src/core/client.rs | 50 ++++++++++++++++++++++++++++++++------ rsocket/src/frame/mod.rs | 4 +++ 6 files changed, 63 insertions(+), 18 deletions(-) diff --git a/examples/cli.rs b/examples/cli.rs index 64b4745..a35ee9c 100644 --- a/examples/cli.rs +++ b/examples/cli.rs @@ -1,9 +1,13 @@ +#[macro_use] +extern crate log; + use rsocket_rust::prelude::*; +use rsocket_rust::Result; use rsocket_rust_transport_tcp::TcpClientTransport; -use std::error::Error; #[tokio::main] -async fn main() -> Result<(), Box> { +async fn main() -> Result<()> { + env_logger::builder().format_timestamp_millis().init(); let client = RSocketFactory::connect() .transport(TcpClientTransport::from("127.0.0.1:7878")) .acceptor(Box::new(|| { @@ -15,8 +19,11 @@ async fn main() -> Result<(), Box> { .expect("Connect failed!"); let req = Payload::builder().set_data_utf8("Ping!").build(); - let res = client.request_response(req).await.expect("Requet failed!"); - println!("request success: response={:?}", res); + + match client.request_response(req).await { + Ok(res) => info!("{:?}", res), + Err(e) => error!("{}", e), + } Ok(()) } diff --git a/examples/echo.rs b/examples/echo.rs index b535fc5..85cf3e2 100644 --- a/examples/echo.rs +++ b/examples/echo.rs @@ -4,14 +4,13 @@ extern crate log; use clap::{App, Arg, SubCommand}; use rsocket_rust::prelude::*; use rsocket_rust::transport::Connection; +use rsocket_rust::Result; use rsocket_rust_transport_tcp::{ TcpClientTransport, TcpServerTransport, UnixClientTransport, UnixServerTransport, }; use rsocket_rust_transport_websocket::{WebsocketClientTransport, WebsocketServerTransport}; use std::fs; -type Result = rsocket_rust::Result; - enum RequestMode { FNF, REQUEST, diff --git a/examples/proxy.rs b/examples/proxy.rs index bffb1ff..dc87313 100644 --- a/examples/proxy.rs +++ b/examples/proxy.rs @@ -3,10 +3,9 @@ extern crate log; use futures::executor::block_on; use rsocket_rust::prelude::*; +use rsocket_rust::Result; use rsocket_rust_transport_tcp::*; -type Result = rsocket_rust::Result; - #[tokio::main] async fn main() -> Result<()> { env_logger::builder().format_timestamp_millis().init(); diff --git a/examples/qps.rs b/examples/qps.rs index e8abcf6..ead2378 100644 --- a/examples/qps.rs +++ b/examples/qps.rs @@ -4,9 +4,9 @@ extern crate log; use clap::{App, Arg}; use rsocket_rust::prelude::*; use rsocket_rust::transport::{Connection, Transport}; +use rsocket_rust::Result; use rsocket_rust_transport_tcp::{TcpClientTransport, UnixClientTransport}; use rsocket_rust_transport_websocket::WebsocketClientTransport; -use std::error::Error; use std::sync::{ atomic::{AtomicU32, Ordering}, Arc, @@ -20,7 +20,7 @@ async fn connect( count: u32, payload_size: usize, notify: Arc, -) -> Result<(), Box> +) -> Result<()> where A: Send + Sync + Transport + 'static, B: Send + Sync + Connection + 'static, @@ -57,7 +57,7 @@ where } #[tokio::main] -async fn main() -> Result<(), Box> { +async fn main() -> Result<()> { env_logger::builder().format_timestamp_millis().init(); let cli = App::new("echo") diff --git a/rsocket/src/core/client.rs b/rsocket/src/core/client.rs index d100b06..868e815 100644 --- a/rsocket/src/core/client.rs +++ b/rsocket/src/core/client.rs @@ -1,4 +1,4 @@ -use crate::error::RSocketError; +use crate::error::{RSocketError, ERR_CONN_CLOSED}; use crate::frame::{self, Frame}; use crate::payload::{Payload, SetupPayload, SetupPayloadBuilder}; use crate::runtime; @@ -7,7 +7,7 @@ use crate::transport::{ self, Acceptor, Connection, DuplexSocket, Reader, Splitter, Transport, Writer, }; use crate::Result; -use futures::{future, FutureExt, SinkExt, StreamExt}; +use futures::{future, select, FutureExt, SinkExt, StreamExt}; use std::error::Error; use std::net::SocketAddr; use std::pin::Pin; @@ -115,6 +115,7 @@ where }; let (snd_tx, mut snd_rx) = mpsc::channel::(super::CHANNEL_SIZE); + let cloned_snd_tx = snd_tx.clone(); let mut socket = DuplexSocket::new(1, snd_tx, splitter).await; let mut cloned_socket = socket.clone(); @@ -126,15 +127,40 @@ where let conn = tp.connect().await?; let (mut sink, mut stream) = conn.split(); + let setup = self.setup.build(); + + // begin write loop + let tick_period = setup.keepalive_interval(); runtime::spawn(async move { - while let Some(frame) = snd_rx.next().await { - if let Err(e) = (&mut sink).write(frame).await { - error!("write frame failed: {}", e); - break; + loop { + // send keepalive if timeout + match tokio::time::timeout(tick_period, snd_rx.next()).await { + Ok(Some(frame)) => { + if let frame::Body::Error(e) = frame.get_body_ref() { + if e.get_code() == ERR_CONN_CLOSED { + break; + } + } + if let Err(e) = (&mut sink).write(frame).await { + error!("write frame failed: {}", e); + break; + } + } + Ok(None) => break, + Err(_) => { + // keepalive + let keepalive_frame = + frame::Keepalive::builder(0, Frame::FLAG_RESPOND).build(); + if let Err(e) = (&mut sink).write(keepalive_frame).await { + error!("write frame failed: {}", e); + break; + } + } } } }); + // begin read loop let closer = self.closer.take(); runtime::spawn(async move { while let Some(next) = stream.read().await { @@ -151,12 +177,22 @@ where } } } + + // workaround: send a notify frame that the connection has been closed. + let close_frame = frame::Error::builder(0, 0) + .set_code(ERR_CONN_CLOSED) + .build(); + if let Err(_) = cloned_snd_tx.send(close_frame).await { + debug!("send close notify frame failed!"); + } + + // invoke on_close handler if let Some(mut invoke) = closer { invoke(); } }); - socket.setup(self.setup.build()).await; + socket.setup(setup).await; Ok(Client::from(socket)) } } diff --git a/rsocket/src/frame/mod.rs b/rsocket/src/frame/mod.rs index 0865524..9ff368d 100644 --- a/rsocket/src/frame/mod.rs +++ b/rsocket/src/frame/mod.rs @@ -187,6 +187,10 @@ impl Frame { self.body } + pub fn get_body_ref(&self) -> &Body { + &self.body + } + pub fn get_flag(&self) -> u16 { self.flag } From 6b751ceb7f58e90ffef804bccadbf181314f2686 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Tue, 8 Dec 2020 22:51:21 +0800 Subject: [PATCH 30/70] fix: convert bytes to utf8 safely (#27) Fix #26 --- justfile | 1 + rsocket-test/tests/test_composite_metadata.rs | 2 +- rsocket/src/extension/composite.rs | 6 ++--- rsocket/src/extension/routing.rs | 2 +- rsocket/src/frame/error.rs | 2 +- rsocket/src/frame/setup.rs | 8 +++---- rsocket/src/payload/misc.rs | 9 ++++++++ rsocket/src/payload/mod.rs | 1 + rsocket/src/payload/normal.rs | 11 +++------ rsocket/src/payload/setup.rs | 23 +++++++++---------- 10 files changed, 35 insertions(+), 30 deletions(-) create mode 100644 rsocket/src/payload/misc.rs diff --git a/justfile b/justfile index 43532ae..9bfdf60 100644 --- a/justfile +++ b/justfile @@ -1,5 +1,6 @@ alias b := bench alias e := echo +alias t := test build: @cargo build diff --git a/rsocket-test/tests/test_composite_metadata.rs b/rsocket-test/tests/test_composite_metadata.rs index c6b39e5..25c2635 100644 --- a/rsocket-test/tests/test_composite_metadata.rs +++ b/rsocket-test/tests/test_composite_metadata.rs @@ -10,7 +10,7 @@ fn test_encode_and_decode() { extension::MimeType::TEXT_PLAIN, *metadatas[0].get_mime_type() ); - assert_eq!("Hello World!", metadatas[0].get_metadata_utf8()); + assert_eq!("Hello World!", metadatas[0].get_metadata_utf8().unwrap()); assert_eq!( MimeType::from("application/not_well"), *metadatas[1].get_mime_type() diff --git a/rsocket/src/extension/composite.rs b/rsocket/src/extension/composite.rs index 712401e..b9df67c 100644 --- a/rsocket/src/extension/composite.rs +++ b/rsocket/src/extension/composite.rs @@ -134,7 +134,7 @@ impl CompositeMetadata { .into()); } let front = bs.split_to(mime_len); - MimeType::Normal(String::from_utf8(front.to_vec()).unwrap()) + MimeType::Normal(String::from_utf8(front.to_vec())?) }; if bs.len() < 3 { @@ -174,8 +174,8 @@ impl CompositeMetadataEntry { &self.metadata } - pub fn get_metadata_utf8(&self) -> &str { - std::str::from_utf8(self.metadata.as_ref()).expect("Invalid UTF-8 bytes.") + pub fn get_metadata_utf8(&self) -> Option<&str> { + std::str::from_utf8(&self.metadata).ok() } } diff --git a/rsocket/src/extension/routing.rs b/rsocket/src/extension/routing.rs index dd9e57b..d273f22 100644 --- a/rsocket/src/extension/routing.rs +++ b/rsocket/src/extension/routing.rs @@ -63,7 +63,7 @@ impl RoutingMetadata { if bf.len() < size { return Err(RSocketError::WithDescription("require more bytes!".into()).into()); } - let tag = String::from_utf8(bf.split_to(size).to_vec()).unwrap(); + let tag = String::from_utf8(bf.split_to(size).to_vec())?; Ok(Some(tag)) } } diff --git a/rsocket/src/frame/error.rs b/rsocket/src/frame/error.rs index ccc86b2..833c427 100644 --- a/rsocket/src/frame/error.rs +++ b/rsocket/src/frame/error.rs @@ -64,7 +64,7 @@ impl Error { pub fn get_data_utf8(&self) -> Option<&str> { match &self.data { - Some(b) => Some(std::str::from_utf8(b.as_ref()).expect("Invalid UTF-8 bytes.")), + Some(b) => std::str::from_utf8(b).ok(), None => None, } } diff --git a/rsocket/src/frame/setup.rs b/rsocket/src/frame/setup.rs index f728a92..452c4e0 100644 --- a/rsocket/src/frame/setup.rs +++ b/rsocket/src/frame/setup.rs @@ -99,12 +99,12 @@ impl Setup { } } - pub fn get_mime_metadata(&self) -> &str { - std::str::from_utf8(self.mime_metadata.as_ref()).expect("Invalid UTF-8 bytes.") + pub fn get_mime_metadata(&self) -> Option<&str> { + std::str::from_utf8(&self.mime_metadata).ok() } - pub fn get_mime_data(&self) -> &str { - std::str::from_utf8(self.mime_data.as_ref()).expect("Invalid UTF-8 bytes.") + pub fn get_mime_data(&self) -> Option<&str> { + std::str::from_utf8(&self.mime_data).ok() } pub fn get_metadata(&self) -> Option<&Bytes> { diff --git a/rsocket/src/payload/misc.rs b/rsocket/src/payload/misc.rs new file mode 100644 index 0000000..1c222e9 --- /dev/null +++ b/rsocket/src/payload/misc.rs @@ -0,0 +1,9 @@ +use bytes::Bytes; + +#[inline] +pub(crate) fn bytes_to_utf8(input: &Option) -> Option<&str> { + match input { + Some(b) => std::str::from_utf8(b).ok(), + None => None, + } +} diff --git a/rsocket/src/payload/mod.rs b/rsocket/src/payload/mod.rs index 014e3bd..82177ce 100644 --- a/rsocket/src/payload/mod.rs +++ b/rsocket/src/payload/mod.rs @@ -1,3 +1,4 @@ +mod misc; mod normal; mod setup; diff --git a/rsocket/src/payload/normal.rs b/rsocket/src/payload/normal.rs index e1987c8..329b4ed 100644 --- a/rsocket/src/payload/normal.rs +++ b/rsocket/src/payload/normal.rs @@ -1,3 +1,4 @@ +use super::misc::bytes_to_utf8; use crate::frame; use bytes::Bytes; @@ -77,17 +78,11 @@ impl Payload { } pub fn data_utf8(&self) -> Option<&str> { - match &self.d { - Some(b) => Some(std::str::from_utf8(b.as_ref()).expect("Invalid UTF-8 bytes.")), - None => None, - } + bytes_to_utf8(&self.d) } pub fn metadata_utf8(&self) -> Option<&str> { - match &self.m { - Some(b) => Some(std::str::from_utf8(b.as_ref()).expect("Invalid UTF-8 bytes.")), - None => None, - } + bytes_to_utf8(&self.m) } pub fn is_empty(&self) -> bool { diff --git a/rsocket/src/payload/setup.rs b/rsocket/src/payload/setup.rs index 1db9498..e882b74 100644 --- a/rsocket/src/payload/setup.rs +++ b/rsocket/src/payload/setup.rs @@ -1,3 +1,4 @@ +use super::misc::bytes_to_utf8; use crate::frame::Setup; use crate::utils::DEFAULT_MIME_TYPE; use bytes::Bytes; @@ -125,17 +126,11 @@ impl SetupPayload { } pub fn metadata_mime_type(&self) -> Option<&str> { - match &self.mime_m { - Some(b) => Some(std::str::from_utf8(b.as_ref()).expect("Invalid UTF-8 bytes.")), - None => None, - } + bytes_to_utf8(&self.mime_m) } pub fn data_mime_type(&self) -> Option<&str> { - match &self.mime_d { - Some(b) => Some(std::str::from_utf8(b.as_ref()).expect("Invalid UTF-8 bytes.")), - None => None, - } + bytes_to_utf8(&self.mime_d) } } @@ -143,14 +138,18 @@ impl From for SetupPayload { fn from(input: Setup) -> SetupPayload { let mut bu = SetupPayload::builder(); // TODO: fill other properties. - bu = bu.set_data_mime_type(input.get_mime_data()); - bu = bu.set_metadata_mime_type(input.get_mime_metadata()); - let ka = (input.get_keepalive(), input.get_lifetime()); + if let Some(m) = input.get_mime_data() { + bu = bu.set_data_mime_type(m); + } + if let Some(m) = input.get_mime_metadata() { + bu = bu.set_metadata_mime_type(m); + } + let keepalive = (input.get_keepalive(), input.get_lifetime()); let (d, m) = input.split(); bu.inner.d = d; bu.inner.m = m; let mut pa = bu.build(); - pa.keepalive = ka; + pa.keepalive = keepalive; pa } } From bb8429f56eb5dc2a56204ec6c57def5e3b8596a0 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Sun, 13 Dec 2020 23:03:54 +0800 Subject: [PATCH 31/70] chore: upgrade deps --- rsocket/Cargo.toml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index ff75318..26e6295 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -12,20 +12,20 @@ description = "rsocket-rust is an implementation of the RSocket protocol in Rust [dependencies] log = "0.4.11" bytes = "0.6.0" -futures = "0.3.7" +futures = "0.3.8" lazy_static = "1.4.0" -async-trait = "0.1.41" +async-trait = "0.1.42" dashmap = "3.11.10" thiserror = "1.0.22" -anyhow = "1.0.34" +anyhow = "1.0.35" [target.'cfg(target_arch = "wasm32")'.dependencies] -wasm-bindgen-futures = "0.4.18" +wasm-bindgen-futures = "0.4.19" [dependencies.tokio] -version = "0.3.3" +version = "0.3.5" default-features = false -features = [ "rt", "rt-multi-thread", "sync", "stream" ] +features = [ "rt", "rt-multi-thread", "sync", "stream", "time" ] [features] default = [] From fbec90dbd3a3c2d87dd670efa55f879e69b0e7c3 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Sun, 13 Dec 2020 23:11:06 +0800 Subject: [PATCH 32/70] chore: prelease 0.6 --- Cargo.toml | 19 ++++------ examples/Cargo.toml | 12 +++---- rsocket-benchmark/Cargo.toml | 40 ---------------------- rsocket-benchmark/benchmark_main.rs | 8 ----- rsocket-benchmark/benchmarks/fibonaccis.rs | 15 -------- rsocket-benchmark/benchmarks/frames.rs | 19 ---------- rsocket-benchmark/benchmarks/mod.rs | 2 -- rsocket-messaging/Cargo.toml | 12 +++---- rsocket-test/Cargo.toml | 18 +++++----- rsocket-transport-tcp/Cargo.toml | 10 +++--- rsocket-transport-wasm/Cargo.toml | 20 +++++------ rsocket-transport-websocket/Cargo.toml | 8 ++--- 12 files changed, 47 insertions(+), 136 deletions(-) delete mode 100644 rsocket-benchmark/Cargo.toml delete mode 100644 rsocket-benchmark/benchmark_main.rs delete mode 100644 rsocket-benchmark/benchmarks/fibonaccis.rs delete mode 100644 rsocket-benchmark/benchmarks/frames.rs delete mode 100644 rsocket-benchmark/benchmarks/mod.rs diff --git a/Cargo.toml b/Cargo.toml index 687b43b..36f0b94 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,16 +1,11 @@ [workspace] members = [ -# core -"rsocket", -# transports -"rsocket-transport-tcp", -"rsocket-transport-websocket", -"rsocket-transport-wasm", -# extra -"rsocket-messaging", -# internal -"examples", -"rsocket-test", -# "rsocket-benchmark", + "rsocket", + "rsocket-transport-tcp", + "rsocket-transport-websocket", + "rsocket-transport-wasm", + "rsocket-messaging", + "examples", + "rsocket-test", ] diff --git a/examples/Cargo.toml b/examples/Cargo.toml index da43620..6476d40 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -7,23 +7,23 @@ publish = false [dev-dependencies] log = "0.4.11" -env_logger = "0.8.1" -futures = "0.3.7" +env_logger = "0.8.2" +futures = "0.3.8" clap = "2.33.3" tokio-postgres = "0.6.0" redis = "0.17.0" [dev-dependencies.rsocket_rust] -path = "../rsocket" +version = "0.6.0" [dev-dependencies.rsocket_rust_transport_tcp] -path = "../rsocket-transport-tcp" +version = "0.6.0" [dev-dependencies.rsocket_rust_transport_websocket] -path = "../rsocket-transport-websocket" +version = "0.6.0" [dev-dependencies.tokio] -version = "0.3.3" +version = "0.3.5" default-features = false features = ["full"] diff --git a/rsocket-benchmark/Cargo.toml b/rsocket-benchmark/Cargo.toml deleted file mode 100644 index 4441f68..0000000 --- a/rsocket-benchmark/Cargo.toml +++ /dev/null @@ -1,40 +0,0 @@ -[package] -name = "rsocket_rust_benchmark" -version = "0.0.0" -authors = ["Jeffsky "] -edition = "2018" -publish = false - -[dev-dependencies] -log = "0.4" -futures = "0.3.5" -env_logger = "0.7.1" -bytes = "0.5.6" -hex = "0.4.2" -rand = "0.7.3" -serde = "1.0.116" -serde_derive = "1.0.116" -criterion = "0.3.3" - -[dev-dependencies.rsocket_rust] -version = "0.5.3" -features = ["frame"] - -[dev-dependencies.rsocket_rust_transport_tcp] -version = "0.5.3" - -[dev-dependencies.rsocket_rust_transport_websocket] -version = "0.5.3" - -[dev-dependencies.rsocket_rust_messaging] -version = "0.5.3" - -[dev-dependencies.tokio] -version = "0.2.22" -default-features = false -features = ["full"] - -[[bench]] -name = "bench_main" -path = "benchmark_main.rs" -harness = false \ No newline at end of file diff --git a/rsocket-benchmark/benchmark_main.rs b/rsocket-benchmark/benchmark_main.rs deleted file mode 100644 index 3b1b991..0000000 --- a/rsocket-benchmark/benchmark_main.rs +++ /dev/null @@ -1,8 +0,0 @@ -use criterion::criterion_main; - -mod benchmarks; - -criterion_main! { - benchmarks::fibonaccis::benches, - benchmarks::frames::benches, -} diff --git a/rsocket-benchmark/benchmarks/fibonaccis.rs b/rsocket-benchmark/benchmarks/fibonaccis.rs deleted file mode 100644 index 12b529a..0000000 --- a/rsocket-benchmark/benchmarks/fibonaccis.rs +++ /dev/null @@ -1,15 +0,0 @@ -use criterion::{black_box, criterion_group, Criterion}; - -fn fibonacci(n: u64) -> u64 { - match n { - 0 => 1, - 1 => 1, - n => fibonacci(n - 1) + fibonacci(n - 2), - } -} - -fn fibonaccis_benchmark(c: &mut Criterion) { - c.bench_function("fib 20", |b| b.iter(|| fibonacci(black_box(20)))); -} - -criterion_group!(benches, fibonaccis_benchmark); diff --git a/rsocket-benchmark/benchmarks/frames.rs b/rsocket-benchmark/benchmarks/frames.rs deleted file mode 100644 index e10a911..0000000 --- a/rsocket-benchmark/benchmarks/frames.rs +++ /dev/null @@ -1,19 +0,0 @@ -use bytes::{Bytes, BytesMut}; -use criterion::{criterion_group, Criterion}; -use rsocket_rust::frame::*; -use rsocket_rust::utils::Writeable; - -fn bench_unmarshal_request_response(c: &mut Criterion) { - c.bench_function("unmarshal request_response", |b| { - b.iter(|| { - let f = RequestResponse::builder(1234, 0) - .set_data(Bytes::from("Hello World")) - .set_metadata(Bytes::from("Foobar")) - .build(); - let mut bf = BytesMut::with_capacity(f.len() as usize); - f.write_to(&mut bf); - }) - }); -} - -criterion_group!(benches, bench_unmarshal_request_response); diff --git a/rsocket-benchmark/benchmarks/mod.rs b/rsocket-benchmark/benchmarks/mod.rs deleted file mode 100644 index a5b1bc1..0000000 --- a/rsocket-benchmark/benchmarks/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod fibonaccis; -pub mod frames; diff --git a/rsocket-messaging/Cargo.toml b/rsocket-messaging/Cargo.toml index 430edc8..79985d1 100644 --- a/rsocket-messaging/Cargo.toml +++ b/rsocket-messaging/Cargo.toml @@ -10,20 +10,20 @@ homepage = "https://github.com/rsocket/rsocket-rust" description = "Communicate with Spring RSocket Messaging." [dependencies] -futures = "0.3.7" +futures = "0.3.8" bytes = "0.6.0" -serde = "1.0.117" -serde_json = "1.0.59" +serde = "1.0.118" +serde_json = "1.0.60" serde_cbor = "0.11.1" hex = "0.4.2" url = "2.2.0" [dependencies.rsocket_rust] -path = "../rsocket" +version = "0.6.0" features = ["frame"] [dependencies.rsocket_rust_transport_tcp] -path = "../rsocket-transport-tcp" +version = "0.6.0" [dependencies.rsocket_rust_transport_websocket] -path = "../rsocket-transport-websocket" +version = "0.6.0" diff --git a/rsocket-test/Cargo.toml b/rsocket-test/Cargo.toml index 2f71bac..ffdfed7 100644 --- a/rsocket-test/Cargo.toml +++ b/rsocket-test/Cargo.toml @@ -7,28 +7,28 @@ publish = false [dev-dependencies] log = "0.4" -futures = "0.3.7" -env_logger = "0.8.1" +futures = "0.3.8" +env_logger = "0.8.2" bytes = "0.6.0" hex = "0.4.2" rand = "0.7.3" -serde = "1.0.117" -serde_derive = "1.0.117" +serde = "1.0.118" +serde_derive = "1.0.118" [dev-dependencies.rsocket_rust] -path = "../rsocket" +version = "0.6.0" features = ["frame"] [dev-dependencies.rsocket_rust_transport_tcp] -path = "../rsocket-transport-tcp" +version = "0.6.0" [dev-dependencies.rsocket_rust_transport_websocket] -path = "../rsocket-transport-websocket" +version = "0.6.0" [dev-dependencies.rsocket_rust_messaging] -path = "../rsocket-messaging" +version = "0.6.0" [dev-dependencies.tokio] -version = "0.3.3" +version = "0.3.5" default-features = false features = ["full"] diff --git a/rsocket-transport-tcp/Cargo.toml b/rsocket-transport-tcp/Cargo.toml index 827cb00..6a6cbc3 100644 --- a/rsocket-transport-tcp/Cargo.toml +++ b/rsocket-transport-tcp/Cargo.toml @@ -11,20 +11,20 @@ description = "TCP RSocket transport implementation." [dependencies] log = "0.4.11" -futures = "0.3.7" +futures = "0.3.8" bytes = "0.6.0" -async-trait = "0.1.41" +async-trait = "0.1.42" [dependencies.rsocket_rust] -path = "../rsocket" +version = "0.6.0" features = ["frame"] [dependencies.tokio] -version = "0.3.3" +version = "0.3.5" default-features = false features = [ "rt", "rt-multi-thread", "net", "sync", "stream", "io-util", "macros" ] [dependencies.tokio-util] -version = "0.5.0" +version = "0.5.1" default-features = false features = ["codec"] diff --git a/rsocket-transport-wasm/Cargo.toml b/rsocket-transport-wasm/Cargo.toml index a3670f6..5256223 100644 --- a/rsocket-transport-wasm/Cargo.toml +++ b/rsocket-transport-wasm/Cargo.toml @@ -11,24 +11,24 @@ description = "WASM Websocket RSocket transport implementation." [dependencies] bytes = "0.6.0" -wasm-bindgen-futures = "0.4.18" -futures-channel = "0.3.7" -futures-util = "0.3.7" -js-sys = "0.3.45" -serde = "1.0.117" -serde_derive = "1.0.117" -async-trait = "0.1.41" +wasm-bindgen-futures = "0.4.19" +futures-channel = "0.3.8" +futures-util = "0.3.8" +js-sys = "0.3.46" +serde = "1.0.118" +serde_derive = "1.0.118" +async-trait = "0.1.42" [dependencies.rsocket_rust] -path = "../rsocket" +version = "0.6.0" features = ["frame"] [dependencies.wasm-bindgen] -version = "0.2.68" +version = "0.2.69" features = ["serde-serialize"] [dependencies.web-sys] -version = "0.3.45" +version = "0.3.46" features = [ "FileReader", "ProgressEvent", diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index 648f65f..93d52f2 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -11,17 +11,17 @@ description = "Websocket RSocket transport implementation." [dependencies] log = "0.4.11" -futures = "0.3.7" +futures = "0.3.8" bytes = "0.6.0" url = "2.2.0" tokio-tungstenite = "0.12.0" -async-trait = "0.1.41" +async-trait = "0.1.42" [dependencies.rsocket_rust] -path = "../rsocket" +version = "0.6.0" features = ["frame"] [dependencies.tokio] -version = "0.3.3" +version = "0.3.5" default-features = false features = [ "rt", "rt-multi-thread", "net", "sync", "stream" ] From fbcbe2bb42f08f922fbd15c7a27b792b8f22d086 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Fri, 25 Dec 2020 16:12:14 +0800 Subject: [PATCH 33/70] chore: bump tokio to v0.3.6 --- examples/Cargo.toml | 8 ++++---- rsocket-messaging/Cargo.toml | 8 ++++---- rsocket-test/Cargo.toml | 12 ++++++------ rsocket-transport-tcp/Cargo.toml | 6 +++--- rsocket-transport-wasm/Cargo.toml | 4 ++-- rsocket-transport-websocket/Cargo.toml | 6 +++--- rsocket/Cargo.toml | 6 +++--- 7 files changed, 25 insertions(+), 25 deletions(-) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 6476d40..3ba817d 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -14,16 +14,16 @@ tokio-postgres = "0.6.0" redis = "0.17.0" [dev-dependencies.rsocket_rust] -version = "0.6.0" +path = "../rsocket" [dev-dependencies.rsocket_rust_transport_tcp] -version = "0.6.0" +path = "../rsocket-transport-tcp" [dev-dependencies.rsocket_rust_transport_websocket] -version = "0.6.0" +path = "../rsocket-transport-websocket" [dev-dependencies.tokio] -version = "0.3.5" +version = "0.3.6" default-features = false features = ["full"] diff --git a/rsocket-messaging/Cargo.toml b/rsocket-messaging/Cargo.toml index 79985d1..d2d03a8 100644 --- a/rsocket-messaging/Cargo.toml +++ b/rsocket-messaging/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_messaging" -version = "0.6.0" +version = "0.6.1" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" @@ -19,11 +19,11 @@ hex = "0.4.2" url = "2.2.0" [dependencies.rsocket_rust] -version = "0.6.0" +path = "../rsocket" features = ["frame"] [dependencies.rsocket_rust_transport_tcp] -version = "0.6.0" +path = "../rsocket-transport-tcp" [dependencies.rsocket_rust_transport_websocket] -version = "0.6.0" +path = "../rsocket-transport-websocket" diff --git a/rsocket-test/Cargo.toml b/rsocket-test/Cargo.toml index ffdfed7..a00a015 100644 --- a/rsocket-test/Cargo.toml +++ b/rsocket-test/Cargo.toml @@ -11,24 +11,24 @@ futures = "0.3.8" env_logger = "0.8.2" bytes = "0.6.0" hex = "0.4.2" -rand = "0.7.3" +rand = "0.8.0" serde = "1.0.118" serde_derive = "1.0.118" [dev-dependencies.rsocket_rust] -version = "0.6.0" +path = "../rsocket" features = ["frame"] [dev-dependencies.rsocket_rust_transport_tcp] -version = "0.6.0" +path = "../rsocket-transport-tcp" [dev-dependencies.rsocket_rust_transport_websocket] -version = "0.6.0" +path = "../rsocket-transport-websocket" [dev-dependencies.rsocket_rust_messaging] -version = "0.6.0" +path = "../rsocket-messaging" [dev-dependencies.tokio] -version = "0.3.5" +version = "0.3.6" default-features = false features = ["full"] diff --git a/rsocket-transport-tcp/Cargo.toml b/rsocket-transport-tcp/Cargo.toml index 6a6cbc3..a68193f 100644 --- a/rsocket-transport-tcp/Cargo.toml +++ b/rsocket-transport-tcp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_tcp" -version = "0.6.0" +version = "0.6.1" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" @@ -16,11 +16,11 @@ bytes = "0.6.0" async-trait = "0.1.42" [dependencies.rsocket_rust] -version = "0.6.0" +path = "../rsocket" features = ["frame"] [dependencies.tokio] -version = "0.3.5" +version = "0.3.6" default-features = false features = [ "rt", "rt-multi-thread", "net", "sync", "stream", "io-util", "macros" ] diff --git a/rsocket-transport-wasm/Cargo.toml b/rsocket-transport-wasm/Cargo.toml index 5256223..e56a615 100644 --- a/rsocket-transport-wasm/Cargo.toml +++ b/rsocket-transport-wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_wasm" -version = "0.6.0" +version = "0.6.1" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" @@ -20,7 +20,7 @@ serde_derive = "1.0.118" async-trait = "0.1.42" [dependencies.rsocket_rust] -version = "0.6.0" +path = "../rsocket" features = ["frame"] [dependencies.wasm-bindgen] diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index 93d52f2..f95b3c1 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_websocket" -version = "0.6.0" +version = "0.6.1" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" @@ -18,10 +18,10 @@ tokio-tungstenite = "0.12.0" async-trait = "0.1.42" [dependencies.rsocket_rust] -version = "0.6.0" +path = "../rsocket" features = ["frame"] [dependencies.tokio] -version = "0.3.5" +version = "0.3.6" default-features = false features = [ "rt", "rt-multi-thread", "net", "sync", "stream" ] diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index 26e6295..27a2a33 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust" -version = "0.6.0" +version = "0.6.1" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" @@ -17,13 +17,13 @@ lazy_static = "1.4.0" async-trait = "0.1.42" dashmap = "3.11.10" thiserror = "1.0.22" -anyhow = "1.0.35" +anyhow = "1.0.36" [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen-futures = "0.4.19" [dependencies.tokio] -version = "0.3.5" +version = "0.3.6" default-features = false features = [ "rt", "rt-multi-thread", "sync", "stream", "time" ] From 0439e93265a17165cd7ee490a0b7887cb61dfcf1 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Sat, 26 Dec 2020 22:08:32 +0800 Subject: [PATCH 34/70] feat: redesign RSocket trait based on async_trait --- examples/Cargo.toml | 3 +- examples/cli.rs | 1 + examples/echo.rs | 5 +- examples/postgres.rs | 22 +-- examples/proxy.rs | 1 + examples/redis.rs | 34 ++--- rsocket-messaging/src/requester.rs | 31 +++-- rsocket-test/tests/test_clients.rs | 5 +- rsocket-transport-wasm/src/misc.rs | 2 +- rsocket/Cargo.toml | 1 + rsocket/src/core/client.rs | 16 ++- rsocket/src/core/server.rs | 3 +- rsocket/src/lib.rs | 11 +- rsocket/src/spi.rs | 80 +---------- rsocket/src/transport/socket.rs | 208 +++++++++++++++-------------- rsocket/src/utils.rs | 75 ++++++++++- 16 files changed, 270 insertions(+), 228 deletions(-) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 3ba817d..3dd8f1a 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -11,7 +11,8 @@ env_logger = "0.8.2" futures = "0.3.8" clap = "2.33.3" tokio-postgres = "0.6.0" -redis = "0.17.0" +redis = "0.16.0" +async-trait = "0.1.42" [dev-dependencies.rsocket_rust] path = "../rsocket" diff --git a/examples/cli.rs b/examples/cli.rs index a35ee9c..d93f3b7 100644 --- a/examples/cli.rs +++ b/examples/cli.rs @@ -2,6 +2,7 @@ extern crate log; use rsocket_rust::prelude::*; +use rsocket_rust::utils::EchoRSocket; use rsocket_rust::Result; use rsocket_rust_transport_tcp::TcpClientTransport; diff --git a/examples/echo.rs b/examples/echo.rs index 85cf3e2..3349b85 100644 --- a/examples/echo.rs +++ b/examples/echo.rs @@ -4,6 +4,7 @@ extern crate log; use clap::{App, Arg, SubCommand}; use rsocket_rust::prelude::*; use rsocket_rust::transport::Connection; +use rsocket_rust::utils::EchoRSocket; use rsocket_rust::Result; use rsocket_rust_transport_tcp::{ TcpClientTransport, TcpServerTransport, UnixClientTransport, UnixServerTransport, @@ -50,7 +51,7 @@ where match mode { RequestMode::FNF => { - cli.fire_and_forget(req).await; + cli.fire_and_forget(req).await?; } RequestMode::STREAM => { let mut results = cli.request_stream(req); @@ -79,7 +80,7 @@ where } } RequestMode::REQUEST => { - let res = cli.request_response(req).await.expect("Request failed!"); + let res = cli.request_response(req).await?; info!("{:?}", res); } } diff --git a/examples/postgres.rs b/examples/postgres.rs index bf79b84..8783477 100644 --- a/examples/postgres.rs +++ b/examples/postgres.rs @@ -1,6 +1,7 @@ #[macro_use] extern crate log; +use async_trait::async_trait; use rsocket_rust::prelude::*; use rsocket_rust::Result; use rsocket_rust_transport_tcp::TcpServerTransport; @@ -24,24 +25,23 @@ struct Dao { client: Arc, } +#[async_trait] impl RSocket for Dao { - fn request_response(&self, _: Payload) -> Mono> { + async fn request_response(&self, _: Payload) -> Result { let client = self.client.clone(); - Box::pin(async move { - let row = client - .query_one("SELECT 'world' AS hello", &[]) - .await - .expect("Execute SQL failed!"); - let result: String = row.get("hello"); - Ok(Payload::builder().set_data_utf8(&result).build()) - }) + let row = client + .query_one("SELECT 'world' AS hello", &[]) + .await + .expect("Execute SQL failed!"); + let result: String = row.get("hello"); + Ok(Payload::builder().set_data_utf8(&result).build()) } - fn metadata_push(&self, _: Payload) -> Mono<()> { + async fn metadata_push(&self, _: Payload) -> Result<()> { unimplemented!() } - fn fire_and_forget(&self, _: Payload) -> Mono<()> { + async fn fire_and_forget(&self, _: Payload) -> Result<()> { unimplemented!() } diff --git a/examples/proxy.rs b/examples/proxy.rs index dc87313..c3b4b34 100644 --- a/examples/proxy.rs +++ b/examples/proxy.rs @@ -3,6 +3,7 @@ extern crate log; use futures::executor::block_on; use rsocket_rust::prelude::*; +use rsocket_rust::utils::EchoRSocket; use rsocket_rust::Result; use rsocket_rust_transport_tcp::*; diff --git a/examples/redis.rs b/examples/redis.rs index b268616..964d5a9 100644 --- a/examples/redis.rs +++ b/examples/redis.rs @@ -1,3 +1,4 @@ +use async_trait::async_trait; use redis::Client as RedisClient; use rsocket_rust::prelude::*; use rsocket_rust::Result; @@ -28,33 +29,34 @@ impl FromStr for RedisDao { } } +#[async_trait] impl RSocket for RedisDao { - fn request_response(&self, req: Payload) -> Mono> { + async fn request_response(&self, req: Payload) -> Result { let client = self.inner.clone(); - - Box::pin(async move { - let mut conn: redis::aio::Connection = client - .get_async_connection() - .await - .expect("Connect redis failed!"); - let value: String = redis::cmd("GET") - .arg(&[req.data_utf8()]) - .query_async(&mut conn) - .await - .unwrap_or("".to_owned()); - Ok(Payload::builder().set_data_utf8(&value).build()) - }) + let mut conn: redis::aio::Connection = client + .get_async_connection() + .await + .expect("Connect redis failed!"); + let value: String = redis::cmd("GET") + .arg(&[req.data_utf8()]) + .query_async(&mut conn) + .await + .unwrap_or("".to_owned()); + Ok(Payload::builder().set_data_utf8(&value).build()) } - fn metadata_push(&self, _req: Payload) -> Mono<()> { + async fn metadata_push(&self, _req: Payload) -> Result<()> { unimplemented!() } - fn fire_and_forget(&self, _req: Payload) -> Mono<()> { + + async fn fire_and_forget(&self, _req: Payload) -> Result<()> { unimplemented!() } + fn request_stream(&self, _req: Payload) -> Flux> { unimplemented!() } + fn request_channel(&self, _reqs: Flux>) -> Flux> { unimplemented!() } diff --git a/rsocket-messaging/src/requester.rs b/rsocket-messaging/src/requester.rs index 93dbad4..435e08e 100644 --- a/rsocket-messaging/src/requester.rs +++ b/rsocket-messaging/src/requester.rs @@ -259,8 +259,7 @@ impl RequestSpec { pub async fn retrieve(self) -> Result<()> { let (req, _mime_type, rsocket) = self.preflight()?; - rsocket.fire_and_forget(req).await; - Ok(()) + rsocket.fire_and_forget(req).await } pub async fn retrieve_mono(self) -> Unpacker { @@ -364,10 +363,16 @@ fn do_unmarshal(mime_type: &MimeType, raw: &Bytes) -> Result> where T: Sized + DeserializeOwned, { - // TODO: support more mime types - match *mime_type { - MimeType::APPLICATION_JSON => Ok(Some(unmarshal(misc::json(), &raw.as_ref())?)), - MimeType::APPLICATION_CBOR => Ok(Some(unmarshal(misc::cbor(), &raw.as_ref())?)), + match mime_type.as_u8() { + Some(code) => { + if code == MimeType::APPLICATION_JSON.as_u8().unwrap() { + Ok(Some(unmarshal(misc::json(), &raw.as_ref())?)) + } else if code == MimeType::APPLICATION_CBOR.as_u8().unwrap() { + Ok(Some(unmarshal(misc::cbor(), &raw.as_ref())?)) + } else { + Err(RSocketError::WithDescription("unsupported mime type!".into()).into()) + } + } _ => Err(RSocketError::WithDescription("unsupported mime type!".into()).into()), } } @@ -376,10 +381,16 @@ fn do_marshal(mime_type: &MimeType, data: &T) -> Result> where T: Sized + Serialize, { - // TODO: support more mime types - match *mime_type { - MimeType::APPLICATION_JSON => marshal(misc::json(), data), - MimeType::APPLICATION_CBOR => marshal(misc::cbor(), data), + match mime_type.as_u8() { + Some(code) => { + if code == MimeType::APPLICATION_JSON.as_u8().unwrap() { + marshal(misc::json(), data) + } else if code == MimeType::APPLICATION_CBOR.as_u8().unwrap() { + marshal(misc::cbor(), data) + } else { + Err(RSocketError::WithDescription("unsupported mime type!".into()).into()) + } + } _ => Err(RSocketError::WithDescription("unsupported mime type!".into()).into()), } } diff --git a/rsocket-test/tests/test_clients.rs b/rsocket-test/tests/test_clients.rs index a262628..f782398 100644 --- a/rsocket-test/tests/test_clients.rs +++ b/rsocket-test/tests/test_clients.rs @@ -3,6 +3,7 @@ extern crate log; use futures::stream; use rsocket_rust::prelude::*; +use rsocket_rust::utils::EchoRSocket; use rsocket_rust::Client; use rsocket_rust_transport_tcp::{ TcpClientTransport, TcpServerTransport, UnixClientTransport, UnixServerTransport, @@ -216,13 +217,13 @@ async fn exec_request_response(socket: &Client) { async fn exec_metadata_push(socket: &Client) { let pa = Payload::builder().set_metadata_utf8("Hello World!").build(); // metadata push - socket.metadata_push(pa).await; + let _ = socket.metadata_push(pa).await; } async fn exec_fire_and_forget(socket: &Client) { // request fnf let fnf = Payload::from("Hello World!"); - socket.fire_and_forget(fnf).await; + let _ = socket.fire_and_forget(fnf).await; } async fn exec_request_stream(socket: &Client) { diff --git a/rsocket-transport-wasm/src/misc.rs b/rsocket-transport-wasm/src/misc.rs index 4682622..a30040a 100644 --- a/rsocket-transport-wasm/src/misc.rs +++ b/rsocket-transport-wasm/src/misc.rs @@ -87,7 +87,7 @@ impl JsClient { let request: JsPayload = request.into_serde().unwrap(); future_to_promise(async move { - inner.fire_and_forget(request.into()).await; + let _ = inner.fire_and_forget(request.into()).await; Ok(JsValue::NULL) }) } diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index 27a2a33..9009350 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -18,6 +18,7 @@ async-trait = "0.1.42" dashmap = "3.11.10" thiserror = "1.0.22" anyhow = "1.0.36" +async-stream = "0.3.0" [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen-futures = "0.4.19" diff --git a/rsocket/src/core/client.rs b/rsocket/src/core/client.rs index 868e815..a9e7fd4 100644 --- a/rsocket/src/core/client.rs +++ b/rsocket/src/core/client.rs @@ -2,11 +2,12 @@ use crate::error::{RSocketError, ERR_CONN_CLOSED}; use crate::frame::{self, Frame}; use crate::payload::{Payload, SetupPayload, SetupPayloadBuilder}; use crate::runtime; -use crate::spi::{ClientResponder, Flux, Mono, RSocket}; +use crate::spi::{ClientResponder, Flux, RSocket}; use crate::transport::{ self, Acceptor, Connection, DuplexSocket, Reader, Splitter, Transport, Writer, }; use crate::Result; +use async_trait::async_trait; use futures::{future, select, FutureExt, SinkExt, StreamExt}; use std::error::Error; use std::net::SocketAddr; @@ -209,17 +210,18 @@ impl Client { } } +#[async_trait] impl RSocket for Client { - fn metadata_push(&self, req: Payload) -> Mono<()> { - self.socket.metadata_push(req) + async fn metadata_push(&self, req: Payload) -> Result<()> { + self.socket.metadata_push(req).await } - fn fire_and_forget(&self, req: Payload) -> Mono<()> { - self.socket.fire_and_forget(req) + async fn fire_and_forget(&self, req: Payload) -> Result<()> { + self.socket.fire_and_forget(req).await } - fn request_response(&self, req: Payload) -> Mono> { - self.socket.request_response(req) + async fn request_response(&self, req: Payload) -> Result { + self.socket.request_response(req).await } fn request_stream(&self, req: Payload) -> Flux> { diff --git a/rsocket/src/core/server.rs b/rsocket/src/core/server.rs index bd9c3b0..826a291 100644 --- a/rsocket/src/core/server.rs +++ b/rsocket/src/core/server.rs @@ -2,10 +2,11 @@ use crate::error::RSocketError; use crate::frame::{self, Frame}; use crate::payload::SetupPayload; use crate::runtime; -use crate::spi::{EmptyRSocket, RSocket, ServerResponder}; +use crate::spi::{RSocket, ServerResponder}; use crate::transport::{ Acceptor, Connection, DuplexSocket, ServerTransport, Splitter, Transport, MIN_MTU, }; +use crate::utils::EmptyRSocket; use crate::Result; use std::error::Error; use std::future::Future; diff --git a/rsocket/src/lib.rs b/rsocket/src/lib.rs index 7bb8890..750a0c3 100644 --- a/rsocket/src/lib.rs +++ b/rsocket/src/lib.rs @@ -37,11 +37,12 @@ //! //! ```no_run,ignore //! use rsocket_rust::prelude::*; +//! use rsocket_rust::utils::EchoRSocket; +//! use rsocket_rust::Result; //! use rsocket_rust_transport_tcp::TcpServerTransport; -//! use std::error::Error; //! //! #[tokio::main] -//! async fn main() -> Result<(), Box> { +//! async fn main() -> Result<()> { //! RSocketFactory::receive() //! .transport(TcpServerTransport::from("127.0.0.1:7878")) //! .acceptor(Box::new(|setup, socket| { @@ -65,11 +66,12 @@ //! //! ```no_run,ignore //! use rsocket_rust::prelude::*; +//! use rsocket_rust::utils::EchoRSocket; +//! use rsocket_rust::Result; //! use rsocket_rust_transport_tcp::TcpClientTransport; -//! use std::error::Error; //! //! #[tokio::main] -//! async fn main() -> Result<(), Box> { +//! async fn main() -> Result<()> { //! let client = RSocketFactory::connect() //! .transport(TcpClientTransport::from("127.0.0.1:7878")) //! .acceptor(Box::new(|| { @@ -112,6 +114,5 @@ pub mod utils; pub type Error = Box; pub type Result = anyhow::Result; -pub type PinBoxFuture = std::pin::Pin>>; pub use crate::core::{Client, ClientBuilder, ServerBuilder}; diff --git a/rsocket/src/spi.rs b/rsocket/src/spi.rs index 0ba7db5..dcae07e 100644 --- a/rsocket/src/spi.rs +++ b/rsocket/src/spi.rs @@ -1,8 +1,8 @@ use crate::error::{self, RSocketError}; use crate::payload::{Payload, SetupPayload}; use crate::{runtime, Error, Result}; -use futures::future; -use futures::{pin_mut, FutureExt, Sink, SinkExt, Stream, StreamExt}; +use async_trait::async_trait; +use futures::Stream; use std::future::Future; use std::pin::Pin; use std::sync::Arc; @@ -12,81 +12,13 @@ pub type ClientResponder = Box Box>; pub type ServerResponder = Box) -> Result>>; -pub type Mono = Pin>>; pub type Flux = Pin>>; +#[async_trait] pub trait RSocket: Sync + Send { - fn metadata_push(&self, req: Payload) -> Mono<()>; - fn fire_and_forget(&self, req: Payload) -> Mono<()>; - fn request_response(&self, req: Payload) -> Mono>; + async fn metadata_push(&self, req: Payload) -> Result<()>; + async fn fire_and_forget(&self, req: Payload) -> Result<()>; + async fn request_response(&self, req: Payload) -> Result; fn request_stream(&self, req: Payload) -> Flux>; fn request_channel(&self, reqs: Flux>) -> Flux>; } - -pub struct EchoRSocket; - -impl RSocket for EchoRSocket { - fn metadata_push(&self, req: Payload) -> Mono<()> { - info!("{:?}", req); - Box::pin(async {}) - } - - fn fire_and_forget(&self, req: Payload) -> Mono<()> { - info!("{:?}", req); - Box::pin(async {}) - } - - fn request_response(&self, req: Payload) -> Mono> { - info!("{:?}", req); - Box::pin(async move { Ok(req) }) - } - - fn request_stream(&self, req: Payload) -> Flux> { - info!("{:?}", req); - // repeat 3 times. - Box::pin(futures::stream::iter(vec![ - Ok(req.clone()), - Ok(req.clone()), - Ok(req), - ])) - } - - fn request_channel(&self, mut reqs: Flux>) -> Flux> { - let (sender, receiver) = mpsc::unbounded_channel(); - tokio::spawn(async move { - while let Some(it) = reqs.next().await { - info!("{:?}", it); - sender.send(it).unwrap(); - } - }); - Box::pin(receiver) - // or returns directly - // reqs - } -} - -pub(crate) struct EmptyRSocket; - -impl RSocket for EmptyRSocket { - fn metadata_push(&self, _req: Payload) -> Mono<()> { - Box::pin(async {}) - } - - fn fire_and_forget(&self, _req: Payload) -> Mono<()> { - Box::pin(async {}) - } - - fn request_response(&self, _req: Payload) -> Mono> { - Box::pin(future::err( - RSocketError::ApplicationException("NOT_IMPLEMENT".into()).into(), - )) - } - - fn request_stream(&self, _req: Payload) -> Flux> { - Box::pin(futures::stream::empty()) - } - - fn request_channel(&self, _reqs: Flux>) -> Flux> { - Box::pin(futures::stream::empty()) - } -} diff --git a/rsocket/src/transport/socket.rs b/rsocket/src/transport/socket.rs index 6a6cf33..9d08570 100644 --- a/rsocket/src/transport/socket.rs +++ b/rsocket/src/transport/socket.rs @@ -4,16 +4,19 @@ use super::spi::*; use crate::error::{self, RSocketError}; use crate::frame::{self, Body, Frame}; use crate::payload::{Payload, SetupPayload}; -use crate::spi::{EmptyRSocket, Flux, Mono, RSocket}; +use crate::spi::{Flux, RSocket}; +use crate::utils::EmptyRSocket; use crate::{runtime, Result}; +use async_stream::stream; +use async_trait::async_trait; use bytes::{Buf, BufMut, Bytes, BytesMut}; use dashmap::{mapref::entry::Entry, DashMap}; use futures::{Sink, SinkExt, Stream, StreamExt}; use std::future::Future; use std::pin::Pin; -use std::sync::{Arc, RwLock}; +use std::sync::Arc; use tokio::prelude::*; -use tokio::sync::{mpsc, oneshot}; +use tokio::sync::{mpsc, oneshot, RwLock}; #[derive(Clone)] pub(crate) struct DuplexSocket { @@ -115,7 +118,10 @@ impl DuplexSocket { debug_frame(false, &msg); match msg.get_body() { Body::Setup(v) => { - if let Err(e) = self.on_setup(acceptor, sid, flag, SetupPayload::from(v)) { + if let Err(e) = self + .on_setup(acceptor, sid, flag, SetupPayload::from(v)) + .await + { let errmsg = format!("{}", e); let sending = frame::Error::builder(0, 0) .set_code(error::ERR_REJECT_SETUP) @@ -334,7 +340,7 @@ impl DuplexSocket { } #[inline] - fn on_setup( + async fn on_setup( &self, acceptor: &Option, sid: u32, @@ -343,16 +349,16 @@ impl DuplexSocket { ) -> Result<()> { match acceptor { None => { - self.responder.set(Box::new(EmptyRSocket)); + self.responder.set(Box::new(EmptyRSocket)).await; Ok(()) } Some(Acceptor::Simple(gen)) => { - self.responder.set(gen()); + self.responder.set(gen()).await; Ok(()) } Some(Acceptor::Generate(gen)) => match gen(setup, Box::new(self.clone())) { Ok(it) => { - self.responder.set(it); + self.responder.set(it).await; Ok(()) } Err(e) => Err(e), @@ -362,7 +368,9 @@ impl DuplexSocket { #[inline] async fn on_fire_and_forget(&mut self, sid: u32, input: Payload) { - self.responder.fire_and_forget(input).await + if let Err(e) = self.responder.fire_and_forget(input).await { + error!("respond fire_and_forget failed: {:?}", e); + } } #[inline] @@ -484,7 +492,9 @@ impl DuplexSocket { #[inline] async fn on_metadata_push(&mut self, input: Payload) { - self.responder.metadata_push(input).await + if let Err(e) = self.responder.metadata_push(input).await { + error!("response metadata_push failed: {:?}", e); + } } #[inline] @@ -617,82 +627,77 @@ impl DuplexSocket { } } +#[async_trait] impl RSocket for DuplexSocket { - fn metadata_push(&self, req: Payload) -> Mono<()> { + async fn metadata_push(&self, req: Payload) -> Result<()> { let sid = self.seq.next(); let tx = self.tx.clone(); - Box::pin(async move { - let (_d, m) = req.split(); - let mut bu = frame::MetadataPush::builder(sid, 0); - if let Some(b) = m { - bu = bu.set_metadata(b); - } - if let Err(e) = tx.send(bu.build()).await { - error!("send metadata_push failed: {}", e); - } - }) + let (_d, m) = req.split(); + let mut bu = frame::MetadataPush::builder(sid, 0); + if let Some(b) = m { + bu = bu.set_metadata(b); + } + tx.send(bu.build()).await?; + Ok(()) + // if let Err(e) = tx.send(bu.build()).await { + // error!("send metadata_push failed: {}", e); + // } } - fn fire_and_forget(&self, req: Payload) -> Mono<()> { + + async fn fire_and_forget(&self, req: Payload) -> Result<()> { let sid = self.seq.next(); let tx = self.tx.clone(); let splitter = self.splitter.clone(); - Box::pin(async move { - match splitter { - Some(sp) => { - let mut cuts: usize = 0; - let mut prev: Option = None; - for next in sp.cut(req, 0) { - if let Some(cur) = prev.take() { - let sending = if cuts == 1 { - // make first frame as request_fnf. - frame::RequestFNF::builder(sid, Frame::FLAG_FOLLOW) - .set_all(cur.split()) - .build() - } else { - // make other frames as payload. - frame::Payload::builder(sid, Frame::FLAG_FOLLOW) - .set_all(cur.split()) - .build() - }; - // send frame - if let Err(e) = tx.send(sending).await { - error!("send fire_and_forget failed: {}", e); - return; - } - } - prev = Some(next); - cuts += 1; - } - let sending = if cuts == 0 { - frame::RequestFNF::builder(sid, 0).build() - } else if cuts == 1 { - frame::RequestFNF::builder(sid, 0) - .set_all(prev.unwrap().split()) - .build() - } else { - frame::Payload::builder(sid, 0) - .set_all(prev.unwrap().split()) - .build() - }; - // send frame - if let Err(e) = tx.send(sending).await { - error!("send fire_and_forget failed: {}", e); - } - } - None => { - let sending = frame::RequestFNF::builder(sid, 0) - .set_all(req.split()) - .build(); - if let Err(e) = tx.send(sending).await { - error!("send fire_and_forget failed: {}", e); + match splitter { + Some(sp) => { + let mut cuts: usize = 0; + let mut prev: Option = None; + for next in sp.cut(req, 0) { + if let Some(cur) = prev.take() { + let sending = if cuts == 1 { + // make first frame as request_fnf. + frame::RequestFNF::builder(sid, Frame::FLAG_FOLLOW) + .set_all(cur.split()) + .build() + } else { + // make other frames as payload. + frame::Payload::builder(sid, Frame::FLAG_FOLLOW) + .set_all(cur.split()) + .build() + }; + // send frame + tx.send(sending).await?; } + prev = Some(next); + cuts += 1; } + + let sending = if cuts == 0 { + frame::RequestFNF::builder(sid, 0).build() + } else if cuts == 1 { + frame::RequestFNF::builder(sid, 0) + .set_all(prev.unwrap().split()) + .build() + } else { + frame::Payload::builder(sid, 0) + .set_all(prev.unwrap().split()) + .build() + }; + // send frame + tx.send(sending).await?; } - }) + None => { + let sending = frame::RequestFNF::builder(sid, 0) + .set_all(req.split()) + .build(); + tx.send(sending).await?; + } + } + Ok(()) } - fn request_response(&self, req: Payload) -> Mono> { + async fn request_response(&self, req: Payload) -> Result { let (tx, rx) = oneshot::channel::>(); let sid = self.seq.next(); let handlers = self.handlers.clone(); @@ -758,14 +763,10 @@ impl RSocket for DuplexSocket { } } }); - Box::pin(async move { - match rx.await { - Ok(v) => v, - Err(_e) => { - Err(RSocketError::WithDescription("request_response failed".into()).into()) - } - } - }) + match rx.await { + Ok(v) => v, + Err(_e) => Err(RSocketError::WithDescription("request_response failed".into()).into()), + } } fn request_stream(&self, input: Payload) -> Flux> { @@ -892,35 +893,48 @@ impl Responder { } } - fn set(&self, rs: Box) { - let mut v = self.inner.write().unwrap(); - *v = rs; + async fn set(&self, rs: Box) { + let mut w = self.inner.write().await; + *w = rs; } } +#[async_trait] impl RSocket for Responder { - fn metadata_push(&self, req: Payload) -> Mono<()> { - let inner = self.inner.read().unwrap(); - (*inner).metadata_push(req) + async fn metadata_push(&self, req: Payload) -> Result<()> { + let inner = self.inner.read().await; + (*inner).metadata_push(req).await } - fn fire_and_forget(&self, req: Payload) -> Mono<()> { - let inner = self.inner.read().unwrap(); - (*inner).fire_and_forget(req) + async fn fire_and_forget(&self, req: Payload) -> Result<()> { + let inner = self.inner.read().await; + (*inner).fire_and_forget(req).await } - fn request_response(&self, req: Payload) -> Mono> { - let inner = self.inner.read().unwrap(); - (*inner).request_response(req) + async fn request_response(&self, req: Payload) -> Result { + let inner = self.inner.read().await; + (*inner).request_response(req).await } fn request_stream(&self, req: Payload) -> Flux> { - let inner = self.inner.read().unwrap(); - (*inner).request_stream(req) + let inner = self.inner.clone(); + Box::pin(stream! { + let r = inner.read().await; + let mut results = (*r).request_stream(req); + while let Some(next) = results.next().await { + yield next; + } + }) } fn request_channel(&self, reqs: Flux>) -> Flux> { - let inner = self.inner.read().unwrap(); - (*inner).request_channel(reqs) + let inner = self.inner.clone(); + Box::pin(stream! { + let r = inner.read().await; + let mut results = (*r).request_channel(reqs); + while let Some(next) = results.next().await{ + yield next; + } + }) } } diff --git a/rsocket/src/utils.rs b/rsocket/src/utils.rs index 346e873..2cec431 100644 --- a/rsocket/src/utils.rs +++ b/rsocket/src/utils.rs @@ -1,12 +1,85 @@ +use super::spi::{Flux, RSocket}; use crate::error::RSocketError; +use crate::payload::Payload; +use crate::Result; +use async_trait::async_trait; use bytes::{Buf, BufMut, Bytes, BytesMut}; +use futures::{pin_mut, FutureExt, Sink, SinkExt, Stream, StreamExt}; use std::error::Error; use std::future::Future; use std::pin::Pin; -use std::result::Result; +use tokio::sync::mpsc; pub const DEFAULT_MIME_TYPE: &str = "application/binary"; +pub struct EchoRSocket; + +#[async_trait] +impl RSocket for EchoRSocket { + async fn metadata_push(&self, req: Payload) -> Result<()> { + info!("{:?}", req); + Ok(()) + } + + async fn fire_and_forget(&self, req: Payload) -> Result<()> { + info!("{:?}", req); + Ok(()) + } + + async fn request_response(&self, req: Payload) -> Result { + info!("{:?}", req); + Ok(req) + } + + fn request_stream(&self, req: Payload) -> Flux> { + info!("{:?}", req); + // repeat 3 times. + Box::pin(futures::stream::iter(vec![ + Ok(req.clone()), + Ok(req.clone()), + Ok(req), + ])) + } + + fn request_channel(&self, mut reqs: Flux>) -> Flux> { + let (sender, receiver) = mpsc::unbounded_channel(); + tokio::spawn(async move { + while let Some(it) = reqs.next().await { + info!("{:?}", it); + sender.send(it).unwrap(); + } + }); + Box::pin(receiver) + // or returns directly + // reqs + } +} + +pub(crate) struct EmptyRSocket; + +#[async_trait] +impl RSocket for EmptyRSocket { + async fn metadata_push(&self, _req: Payload) -> Result<()> { + Err(RSocketError::ApplicationException("UNIMPLEMENT".into()).into()) + } + + async fn fire_and_forget(&self, _req: Payload) -> Result<()> { + Err(RSocketError::ApplicationException("UNIMPLEMENT".into()).into()) + } + + async fn request_response(&self, _req: Payload) -> Result { + Err(RSocketError::ApplicationException("UNIMPLEMENT".into()).into()) + } + + fn request_stream(&self, _req: Payload) -> Flux> { + Box::pin(futures::stream::empty()) + } + + fn request_channel(&self, _reqs: Flux>) -> Flux> { + Box::pin(futures::stream::empty()) + } +} + pub trait Writeable { fn write_to(&self, bf: &mut BytesMut); fn len(&self) -> usize; From 19312c1a7fad88af3b1934adf00380df97006776 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Sun, 27 Dec 2020 20:27:58 +0800 Subject: [PATCH 35/70] chore: fix readme --- README.md | 36 +++++++++-------------- rsocket-messaging/Cargo.toml | 2 +- rsocket-transport-tcp/Cargo.toml | 2 +- rsocket-transport-tcp/README.md | 27 ++++++++--------- rsocket-transport-wasm/Cargo.toml | 2 +- rsocket-transport-websocket/Cargo.toml | 2 +- rsocket-transport-websocket/README.md | 30 +++++++++---------- rsocket/Cargo.toml | 2 +- rsocket/README.md | 40 +++++++++++--------------- 9 files changed, 61 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index 5e839f9..79401e1 100644 --- a/README.md +++ b/README.md @@ -21,32 +21,26 @@ Add dependencies in your `Cargo.toml`. ```toml [dependencies] -tokio = "0.2" -rsocket_rust = "*" +tokio = "0.3.6" +rsocket_rust = "0.7.0" -# choose transport: -# rsocket_rust_transport_tcp = "*" -# rsocket_rust_transport_websocket = "*" +# add transport dependencies: +# rsocket_rust_transport_tcp = "0.7.0" +# rsocket_rust_transport_websocket = "0.7.0" ``` ### Server ```rust -#[macro_use] -extern crate log; - use rsocket_rust::prelude::*; +use rsocket_rust::utils::EchoRSocket; +use rsocket_rust::Result; use rsocket_rust_transport_tcp::TcpServerTransport; -use std::env; -use std::error::Error; #[tokio::main] -async fn main() -> Result<(), Box> { - env_logger::builder().format_timestamp_millis().init(); - let addr = env::args().nth(1).unwrap_or("127.0.0.1:7878".to_string()); - +async fn main() -> Result<()> { RSocketFactory::receive() - .transport(TcpServerTransport::from(addr)) + .transport(TcpServerTransport::from("127.0.0.1:7878")) .acceptor(Box::new(|setup, _socket| { info!("accept setup: {:?}", setup); Ok(Box::new(EchoRSocket)) @@ -63,24 +57,22 @@ async fn main() -> Result<(), Box> { ```rust use rsocket_rust::prelude::*; +use rsocket_rust::Result; use rsocket_rust_transport_tcp::TcpClientTransport; #[tokio::main] -#[test] -async fn test() { +async fn main() -> Result<()> { let cli = RSocketFactory::connect() - .acceptor(Box::new(|| Box::new(EchoRSocket))) .transport(TcpClientTransport::from("127.0.0.1:7878")) .setup(Payload::from("READY!")) .mime_type("text/plain", "text/plain") .start() - .await - .unwrap(); + .await?; let req = Payload::builder() .set_data_utf8("Hello World!") .set_metadata_utf8("Rust") .build(); - let res = cli.request_response(req).await.unwrap(); + let res = cli.request_response(req).await?; println!("got: {:?}", res); cli.close(); } @@ -100,7 +92,7 @@ async fn test() { - [ ] Cancel - [x] Fragmentation - [ ] Resume - - [ ] Keepalive + - [x] Keepalive - QoS - [ ] RequestN - [ ] Lease diff --git a/rsocket-messaging/Cargo.toml b/rsocket-messaging/Cargo.toml index d2d03a8..36a3a4b 100644 --- a/rsocket-messaging/Cargo.toml +++ b/rsocket-messaging/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_messaging" -version = "0.6.1" +version = "0.7.0" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" diff --git a/rsocket-transport-tcp/Cargo.toml b/rsocket-transport-tcp/Cargo.toml index a68193f..7895836 100644 --- a/rsocket-transport-tcp/Cargo.toml +++ b/rsocket-transport-tcp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_tcp" -version = "0.6.1" +version = "0.7.0" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" diff --git a/rsocket-transport-tcp/README.md b/rsocket-transport-tcp/README.md index b1333be..5abd2ec 100644 --- a/rsocket-transport-tcp/README.md +++ b/rsocket-transport-tcp/README.md @@ -6,21 +6,22 @@ Add dependencies in your `Cargo.toml`. ```toml [dependencies] -tokio = "0.2.21" -rsocket_rust = "0.5.3" -rsocket_rust_transport_tcp = "0.5.3" +tokio = "0.3.6" +rsocket_rust = "0.7.0" +rsocket_rust_transport_tcp = "0.7.0" ``` ### Server ```rust use log::info; -use rsocket_rust::prelude::{EchoRSocket, RSocketFactory, ServerResponder}; +use rsocket_rust::prelude::{RSocketFactory, ServerResponder}; +use rsocket_rust::Result; +use rsocket_rust::utils::EchoRSocket; use rsocket_rust_transport_tcp::TcpServerTransport; -use std::error::Error; #[tokio::main] -async fn main() -> Result<(), Box> { +async fn main() -> Result<()> { let transport: TcpServerTransport = TcpServerTransport::from("127.0.0.1:7878"); let responder: ServerResponder = Box::new(|setup, _socket| { @@ -49,29 +50,25 @@ async fn main() -> Result<(), Box> { ```rust use log::info; -use rsocket_rust::prelude::{ClientResponder, EchoRSocket, Payload, RSocket, RSocketFactory}; +use rsocket_rust::prelude::{ClientResponder, Payload, RSocket, RSocketFactory}; +use rsocket_rust::Result; use rsocket_rust_transport_tcp::TcpClientTransport; -use std::error::Error; #[tokio::main] -async fn main() -> Result<(), Box> { - let responder: ClientResponder = Box::new(|| Box::new(EchoRSocket)); - +async fn main() -> Result<()> { let client = RSocketFactory::connect() - .acceptor(responder) .transport(TcpClientTransport::from("127.0.0.1:7878")) .setup(Payload::from("READY!")) .mime_type("text/plain", "text/plain") .start() - .await - .unwrap(); + .await?; let request_payload: Payload = Payload::builder() .set_data_utf8("Hello World!") .set_metadata_utf8("Rust") .build(); - let res = client.request_response(request_payload).await.unwrap(); + let res = client.request_response(request_payload).await?; info!("got: {:?}", res); diff --git a/rsocket-transport-wasm/Cargo.toml b/rsocket-transport-wasm/Cargo.toml index e56a615..ad5fb1d 100644 --- a/rsocket-transport-wasm/Cargo.toml +++ b/rsocket-transport-wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_wasm" -version = "0.6.1" +version = "0.7.0" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index f95b3c1..c188373 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_websocket" -version = "0.6.1" +version = "0.7.0" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" diff --git a/rsocket-transport-websocket/README.md b/rsocket-transport-websocket/README.md index baa1ec3..c12a33a 100644 --- a/rsocket-transport-websocket/README.md +++ b/rsocket-transport-websocket/README.md @@ -6,21 +6,22 @@ Add dependencies in your `Cargo.toml`. ```toml [dependencies] -tokio = "0.2.21" -rsocket_rust = "0.5.3" -rsocket_rust_transport_websocket = "0.5.3" +tokio = "0.3.6" +rsocket_rust = "0.7.0" +rsocket_rust_transport_websocket = "0.7.0" ``` ### Server ```rust use log::info; -use rsocket_rust::prelude::{EchoRSocket, RSocketFactory, ServerResponder}; +use rsocket_rust::prelude::*; +use rsocket_rust::utils::EchoRSocket; +use rsocket_rust::Result; use rsocket_rust_transport_websocket::WebsocketServerTransport; -use std::error::Error; #[tokio::main] -async fn main() -> Result<(), Box> { +async fn main() -> Result<()> { let transport: WebsocketServerTransport = WebsocketServerTransport::from("127.0.0.1:8080"); let responder: ServerResponder = Box::new(|setup, _socket| { @@ -49,29 +50,25 @@ async fn main() -> Result<(), Box> { ```rust use log::info; -use rsocket_rust::prelude::{ClientResponder, EchoRSocket, Payload, RSocket, RSocketFactory}; +use rsocket_rust::prelude::*; +use rsocket_rust::Result; use rsocket_rust_transport_websocket::WebsocketClientTransport; -use std::error::Error; #[tokio::main] -async fn main() -> Result<(), Box> { - let responder: ClientResponder = Box::new(|| Box::new(EchoRSocket)); - +async fn main() -> Result<()> { let client = RSocketFactory::connect() - .acceptor(responder) .transport(WebsocketClientTransport::from("127.0.0.1:8080")) .setup(Payload::from("READY!")) .mime_type("text/plain", "text/plain") .start() - .await - .unwrap(); + .await?; - let request_payload: Payload = Payload::builder() + let request_payload = Payload::builder() .set_data_utf8("Hello World!") .set_metadata_utf8("Rust") .build(); - let res = client.request_response(request_payload).await.unwrap(); + let res = client.request_response(request_payload).await?; info!("got: {:?}", res); @@ -79,5 +76,4 @@ async fn main() -> Result<(), Box> { Ok(()) } - ``` diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index 9009350..fbca125 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust" -version = "0.6.1" +version = "0.7.0" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" diff --git a/rsocket/README.md b/rsocket/README.md index ce8aa3d..ebed0d0 100644 --- a/rsocket/README.md +++ b/rsocket/README.md @@ -10,39 +10,34 @@ Add dependencies in your `Cargo.toml`. ```toml [dependencies] -tokio = "0.2" -rsocket_rust = "*" +tokio = "0.3.6" +rsocket_rust = "0.7.0" -# choose transport: -# rsocket_rust_transport_tcp = "*" -# rsocket_rust_transport_websocket = "*" +# add transport dependencies: +# rsocket_rust_transport_tcp = "0.7.0" +# rsocket_rust_transport_websocket = "0.7.0" ``` ### Server ```rust -#[macro_use] -extern crate log; - use rsocket_rust::prelude::*; +use rsocket_rust::utils::EchoRSocket; +use rsocket_rust::Result; use rsocket_rust_transport_tcp::TcpServerTransport; -use std::env; -use std::error::Error; #[tokio::main] -async fn main() -> Result<(), Box> { - env_logger::builder().format_timestamp_millis().init(); - let addr = env::args().nth(1).unwrap_or("127.0.0.1:7878".to_string()); - +async fn main() -> Result<()> { RSocketFactory::receive() - .transport(TcpServerTransport::from(addr)) + .transport(TcpServerTransport::from("127.0.0.1:7878")) .acceptor(Box::new(|setup, _socket| { - info!("accept setup: {:?}", setup); + println!("accept setup: {:?}", setup); + // Use EchoRSocket as example RSocket, you can implement RSocket trait. Ok(Box::new(EchoRSocket)) // Or you can reject setup // Err(From::from("SETUP_NOT_ALLOW")) })) - .on_start(|| info!("+++++++ echo server started! +++++++")) + .on_start(|| println!("+++++++ echo server started! +++++++")) .serve() .await } @@ -52,26 +47,25 @@ async fn main() -> Result<(), Box> { ```rust use rsocket_rust::prelude::*; +use rsocket_rust::Result; use rsocket_rust_transport_tcp::TcpClientTransport; #[tokio::main] -#[test] -async fn test() { +async fn main() -> Result<()> { let cli = RSocketFactory::connect() - .acceptor(Box::new(|| Box::new(EchoRSocket))) .transport(TcpClientTransport::from("127.0.0.1:7878")) .setup(Payload::from("READY!")) .mime_type("text/plain", "text/plain") .start() - .await - .unwrap(); + .await?; let req = Payload::builder() .set_data_utf8("Hello World!") .set_metadata_utf8("Rust") .build(); - let res = cli.request_response(req).await.unwrap(); + let res = cli.request_response(req).await?; println!("got: {:?}", res); cli.close(); + Ok(()) } ``` From 6c15dfb1cb2cc7436006684e91615f1c575837f6 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Sun, 27 Dec 2020 20:49:12 +0800 Subject: [PATCH 36/70] fix: remove useless examples --- examples/Cargo.toml | 10 ----- examples/docker-compose.yml | 21 ---------- examples/postgres.rs | 76 ------------------------------------- examples/redis.rs | 63 ------------------------------ 4 files changed, 170 deletions(-) delete mode 100644 examples/docker-compose.yml delete mode 100644 examples/postgres.rs delete mode 100644 examples/redis.rs diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 3dd8f1a..135fbb7 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -10,8 +10,6 @@ log = "0.4.11" env_logger = "0.8.2" futures = "0.3.8" clap = "2.33.3" -tokio-postgres = "0.6.0" -redis = "0.16.0" async-trait = "0.1.42" [dev-dependencies.rsocket_rust] @@ -43,11 +41,3 @@ path = "cli.rs" [[example]] name = "qps" path = "qps.rs" - -[[example]] -name = "postgres" -path = "postgres.rs" - -[[example]] -name = "redis" -path = "redis.rs" diff --git a/examples/docker-compose.yml b/examples/docker-compose.yml deleted file mode 100644 index 10c6812..0000000 --- a/examples/docker-compose.yml +++ /dev/null @@ -1,21 +0,0 @@ -version: '3.1' - -services: - postgres: - image: postgres:9.6-alpine - environment: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: postgres - ports: - - 5432:5432 - volumes: - - pgdata:/var/lib/postgresql/data - redis: - image: "redis:3-alpine" - ports: - - "6379:6379" - command: ["redis-server", "--appendonly", "yes"] - -volumes: - pgdata: - driver: local diff --git a/examples/postgres.rs b/examples/postgres.rs deleted file mode 100644 index 8783477..0000000 --- a/examples/postgres.rs +++ /dev/null @@ -1,76 +0,0 @@ -#[macro_use] -extern crate log; - -use async_trait::async_trait; -use rsocket_rust::prelude::*; -use rsocket_rust::Result; -use rsocket_rust_transport_tcp::TcpServerTransport; -use std::sync::Arc; -use tokio_postgres::{Client as PgClient, NoTls}; - -#[tokio::main] -async fn main() -> Result<()> { - env_logger::builder().format_timestamp_millis().init(); - let dao = Dao::try_new().await?; - RSocketFactory::receive() - .acceptor(Box::new(move |_, _| Ok(Box::new(dao.clone())))) - .on_start(Box::new(|| info!("server start success!!!"))) - .transport(TcpServerTransport::from("127.0.0.1:7878")) - .serve() - .await -} - -#[derive(Clone)] -struct Dao { - client: Arc, -} - -#[async_trait] -impl RSocket for Dao { - async fn request_response(&self, _: Payload) -> Result { - let client = self.client.clone(); - let row = client - .query_one("SELECT 'world' AS hello", &[]) - .await - .expect("Execute SQL failed!"); - let result: String = row.get("hello"); - Ok(Payload::builder().set_data_utf8(&result).build()) - } - - async fn metadata_push(&self, _: Payload) -> Result<()> { - unimplemented!() - } - - async fn fire_and_forget(&self, _: Payload) -> Result<()> { - unimplemented!() - } - - fn request_stream(&self, _: Payload) -> Flux> { - unimplemented!() - } - - fn request_channel(&self, _: Flux>) -> Flux> { - unimplemented!() - } -} - -impl Dao { - async fn try_new() -> Result { - let (client, connection) = - tokio_postgres::connect("host=localhost user=postgres password=postgres", NoTls) - .await?; - - // The connection object performs the actual communication with the database, - // so spawn it off to run on its own. - tokio::spawn(async move { - if let Err(e) = connection.await { - eprintln!("connection error: {}", e); - } - }); - - info!("==> create postgres pool success!"); - Ok(Dao { - client: Arc::new(client), - }) - } -} diff --git a/examples/redis.rs b/examples/redis.rs deleted file mode 100644 index 964d5a9..0000000 --- a/examples/redis.rs +++ /dev/null @@ -1,63 +0,0 @@ -use async_trait::async_trait; -use redis::Client as RedisClient; -use rsocket_rust::prelude::*; -use rsocket_rust::Result; -use rsocket_rust_transport_tcp::TcpServerTransport; -use std::str::FromStr; - -#[derive(Clone)] -struct RedisDao { - inner: RedisClient, -} - -#[tokio::main] -async fn main() -> Result<()> { - let dao = RedisDao::from_str("redis://127.0.0.1").expect("Connect redis failed!"); - RSocketFactory::receive() - .acceptor(Box::new(move |_setup, _socket| Ok(Box::new(dao.clone())))) - .transport(TcpServerTransport::from("127.0.0.1:7878")) - .serve() - .await -} - -impl FromStr for RedisDao { - type Err = redis::RedisError; - - fn from_str(s: &str) -> std::result::Result { - let client = redis::Client::open(s)?; - Ok(RedisDao { inner: client }) - } -} - -#[async_trait] -impl RSocket for RedisDao { - async fn request_response(&self, req: Payload) -> Result { - let client = self.inner.clone(); - let mut conn: redis::aio::Connection = client - .get_async_connection() - .await - .expect("Connect redis failed!"); - let value: String = redis::cmd("GET") - .arg(&[req.data_utf8()]) - .query_async(&mut conn) - .await - .unwrap_or("".to_owned()); - Ok(Payload::builder().set_data_utf8(&value).build()) - } - - async fn metadata_push(&self, _req: Payload) -> Result<()> { - unimplemented!() - } - - async fn fire_and_forget(&self, _req: Payload) -> Result<()> { - unimplemented!() - } - - fn request_stream(&self, _req: Payload) -> Flux> { - unimplemented!() - } - - fn request_channel(&self, _reqs: Flux>) -> Flux> { - unimplemented!() - } -} From 29754e06d171eec27e65403f308ad6e2817eb0a2 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Tue, 29 Dec 2020 22:49:39 +0800 Subject: [PATCH 37/70] fix: simplify Option convert --- rsocket-transport-tcp/src/connection/tcp.rs | 9 ++++----- rsocket-transport-tcp/src/connection/uds.rs | 9 ++++----- rsocket-transport-wasm/src/connection.rs | 5 +---- rsocket-transport-wasm/src/misc.rs | 5 +---- rsocket/src/core/client.rs | 5 +---- rsocket/src/core/server.rs | 6 +----- rsocket/src/frame/error.rs | 5 +---- rsocket/src/frame/keepalive.rs | 5 +---- rsocket/src/frame/lease.rs | 5 +---- rsocket/src/frame/metadata_push.rs | 5 +---- rsocket/src/frame/payload.rs | 10 ++-------- rsocket/src/frame/request_channel.rs | 10 ++-------- rsocket/src/frame/request_fnf.rs | 10 ++-------- rsocket/src/frame/request_response.rs | 10 ++-------- rsocket/src/frame/request_stream.rs | 10 ++-------- rsocket/src/frame/setup.rs | 15 +++------------ rsocket/src/payload/normal.rs | 10 ++-------- rsocket/src/payload/setup.rs | 10 ++-------- 18 files changed, 33 insertions(+), 111 deletions(-) diff --git a/rsocket-transport-tcp/src/connection/tcp.rs b/rsocket-transport-tcp/src/connection/tcp.rs index 8813d51..456a5c9 100644 --- a/rsocket-transport-tcp/src/connection/tcp.rs +++ b/rsocket-transport-tcp/src/connection/tcp.rs @@ -34,11 +34,10 @@ impl Writer for InnerWriter { #[async_trait] impl Reader for InnerReader { async fn read(&mut self) -> Option> { - match self.stream.next().await { - Some(Ok(frame)) => Some(Ok(frame)), - Some(Err(e)) => Some(Err(RSocketError::IO(e).into())), - None => None, - } + self.stream + .next() + .await + .map(|next| next.map_err(|e| RSocketError::IO(e).into())) } } diff --git a/rsocket-transport-tcp/src/connection/uds.rs b/rsocket-transport-tcp/src/connection/uds.rs index b32c3cf..4050cf7 100644 --- a/rsocket-transport-tcp/src/connection/uds.rs +++ b/rsocket-transport-tcp/src/connection/uds.rs @@ -49,11 +49,10 @@ impl Writer for InnerWriter { #[async_trait] impl Reader for InnerReader { async fn read(&mut self) -> Option> { - match self.stream.next().await { - Some(Ok(frame)) => Some(Ok(frame)), - Some(Err(e)) => Some(Err(RSocketError::IO(e).into())), - None => None, - } + self.stream + .next() + .await + .map(|it| it.map_err(|e| RSocketError::IO(e).into())) } } diff --git a/rsocket-transport-wasm/src/connection.rs b/rsocket-transport-wasm/src/connection.rs index 0a1aa33..a93f921 100644 --- a/rsocket-transport-wasm/src/connection.rs +++ b/rsocket-transport-wasm/src/connection.rs @@ -37,10 +37,7 @@ impl Writer for InnerWriter { #[async_trait] impl Reader for InnerReader { async fn read(&mut self) -> Option> { - match self.rx.next().await { - Some(frame) => Some(Ok(frame)), - None => None, - } + self.rx.next().await.map(|frame| Ok(frame)) } } diff --git a/rsocket-transport-wasm/src/misc.rs b/rsocket-transport-wasm/src/misc.rs index a30040a..96d1dcb 100644 --- a/rsocket-transport-wasm/src/misc.rs +++ b/rsocket-transport-wasm/src/misc.rs @@ -98,10 +98,7 @@ fn to_vec(input: JsValue) -> Option> { if input.is_null() || input.is_undefined() { None } else if input.is_string() { - match input.as_string() { - Some(s) => Some(s.into_bytes()), - None => None, - } + input.as_string().map(|s| s.into_bytes()) } else { Some(Uint8Array::from(input).to_vec()) } diff --git a/rsocket/src/core/client.rs b/rsocket/src/core/client.rs index a9e7fd4..3cd5f99 100644 --- a/rsocket/src/core/client.rs +++ b/rsocket/src/core/client.rs @@ -120,10 +120,7 @@ where let mut socket = DuplexSocket::new(1, snd_tx, splitter).await; let mut cloned_socket = socket.clone(); - let acceptor: Option = match self.responder { - Some(it) => Some(Acceptor::Simple(Arc::new(it))), - None => None, - }; + let acceptor: Option = self.responder.map(|it| Acceptor::Simple(Arc::new(it))); let conn = tp.connect().await?; let (mut sink, mut stream) = conn.split(); diff --git a/rsocket/src/core/server.rs b/rsocket/src/core/server.rs index 826a291..d1b03c4 100644 --- a/rsocket/src/core/server.rs +++ b/rsocket/src/core/server.rs @@ -65,11 +65,7 @@ where pub async fn serve(mut self) -> Result<()> { let mut server_transport = self.transport.take().expect("missing transport"); - - let acceptor = match self.on_setup { - Some(v) => Some(Acceptor::Generate(Arc::new(v))), - None => None, - }; + let acceptor = self.on_setup.map(|v| Acceptor::Generate(Arc::new(v))); let mtu = self.mtu; diff --git a/rsocket/src/frame/error.rs b/rsocket/src/frame/error.rs index 833c427..ffbf2b1 100644 --- a/rsocket/src/frame/error.rs +++ b/rsocket/src/frame/error.rs @@ -70,10 +70,7 @@ impl Error { } pub fn get_data(&self) -> Option<&Bytes> { - match &self.data { - Some(b) => Some(b), - None => None, - } + self.data.as_ref() } pub fn get_code(&self) -> u32 { diff --git a/rsocket/src/frame/keepalive.rs b/rsocket/src/frame/keepalive.rs index 074cf86..6e0d836 100644 --- a/rsocket/src/frame/keepalive.rs +++ b/rsocket/src/frame/keepalive.rs @@ -68,10 +68,7 @@ impl Keepalive { } pub fn get_data(&self) -> Option<&Bytes> { - match &self.data { - Some(b) => Some(b), - None => None, - } + self.data.as_ref() } pub fn split(self) -> (Option, Option) { diff --git a/rsocket/src/frame/lease.rs b/rsocket/src/frame/lease.rs index 938969c..3b305a2 100644 --- a/rsocket/src/frame/lease.rs +++ b/rsocket/src/frame/lease.rs @@ -78,10 +78,7 @@ impl Lease { } pub fn get_metadata(&self) -> Option<&Bytes> { - match &self.metadata { - Some(b) => Some(b), - None => None, - } + self.metadata.as_ref() } pub fn get_ttl(&self) -> u32 { diff --git a/rsocket/src/frame/metadata_push.rs b/rsocket/src/frame/metadata_push.rs index 213845e..edd1605 100644 --- a/rsocket/src/frame/metadata_push.rs +++ b/rsocket/src/frame/metadata_push.rs @@ -44,10 +44,7 @@ impl MetadataPush { } pub fn get_metadata(&self) -> Option<&Bytes> { - match &self.metadata { - Some(b) => Some(b), - None => None, - } + self.metadata.as_ref() } pub fn split(self) -> (Option, Option) { diff --git a/rsocket/src/frame/payload.rs b/rsocket/src/frame/payload.rs index 6a7e923..c8deff7 100644 --- a/rsocket/src/frame/payload.rs +++ b/rsocket/src/frame/payload.rs @@ -69,17 +69,11 @@ impl Payload { } pub fn get_metadata(&self) -> Option<&Bytes> { - match &self.metadata { - Some(b) => Some(b), - None => None, - } + self.metadata.as_ref() } pub fn get_data(&self) -> Option<&Bytes> { - match &self.data { - Some(b) => Some(b), - None => None, - } + self.data.as_ref() } pub fn split(self) -> (Option, Option) { diff --git a/rsocket/src/frame/request_channel.rs b/rsocket/src/frame/request_channel.rs index 9c8a681..f7ba6e8 100644 --- a/rsocket/src/frame/request_channel.rs +++ b/rsocket/src/frame/request_channel.rs @@ -89,16 +89,10 @@ impl RequestChannel { } pub fn get_metadata(&self) -> Option<&Bytes> { - match &self.metadata { - Some(b) => Some(b), - None => None, - } + self.metadata.as_ref() } pub fn get_data(&self) -> Option<&Bytes> { - match &self.data { - Some(b) => Some(b), - None => None, - } + self.data.as_ref() } pub fn split(self) -> (Option, Option) { diff --git a/rsocket/src/frame/request_fnf.rs b/rsocket/src/frame/request_fnf.rs index 30c9d1e..80411a3 100644 --- a/rsocket/src/frame/request_fnf.rs +++ b/rsocket/src/frame/request_fnf.rs @@ -70,17 +70,11 @@ impl RequestFNF { } pub fn get_metadata(&self) -> Option<&Bytes> { - match &self.metadata { - Some(b) => Some(b), - None => None, - } + self.metadata.as_ref() } pub fn get_data(&self) -> Option<&Bytes> { - match &self.data { - Some(b) => Some(b), - None => None, - } + self.data.as_ref() } pub fn split(self) -> (Option, Option) { diff --git a/rsocket/src/frame/request_response.rs b/rsocket/src/frame/request_response.rs index df10bbb..f2a21de 100644 --- a/rsocket/src/frame/request_response.rs +++ b/rsocket/src/frame/request_response.rs @@ -70,17 +70,11 @@ impl RequestResponse { } pub fn get_metadata(&self) -> Option<&Bytes> { - match &self.metadata { - Some(b) => Some(b), - None => None, - } + self.metadata.as_ref() } pub fn get_data(&self) -> Option<&Bytes> { - match &self.data { - Some(b) => Some(b), - None => None, - } + self.data.as_ref() } pub fn split(self) -> (Option, Option) { diff --git a/rsocket/src/frame/request_stream.rs b/rsocket/src/frame/request_stream.rs index e0cb18d..8ff9326 100644 --- a/rsocket/src/frame/request_stream.rs +++ b/rsocket/src/frame/request_stream.rs @@ -84,17 +84,11 @@ impl RequestStream { } pub fn get_metadata(&self) -> Option<&Bytes> { - match &self.metadata { - Some(b) => Some(b), - None => None, - } + self.metadata.as_ref() } pub fn get_data(&self) -> Option<&Bytes> { - match &self.data { - Some(b) => Some(b), - None => None, - } + self.data.as_ref() } pub fn split(self) -> (Option, Option) { diff --git a/rsocket/src/frame/setup.rs b/rsocket/src/frame/setup.rs index 452c4e0..7c99531 100644 --- a/rsocket/src/frame/setup.rs +++ b/rsocket/src/frame/setup.rs @@ -93,10 +93,7 @@ impl Setup { } pub fn get_token(&self) -> Option<&Bytes> { - match &self.token { - Some(b) => Some(b), - None => None, - } + self.token.as_ref() } pub fn get_mime_metadata(&self) -> Option<&str> { @@ -108,17 +105,11 @@ impl Setup { } pub fn get_metadata(&self) -> Option<&Bytes> { - match &self.metadata { - Some(b) => Some(b), - None => None, - } + self.metadata.as_ref() } pub fn get_data(&self) -> Option<&Bytes> { - match &self.data { - Some(b) => Some(b), - None => None, - } + self.data.as_ref() } pub fn split(self) -> (Option, Option) { diff --git a/rsocket/src/payload/normal.rs b/rsocket/src/payload/normal.rs index 329b4ed..f0c3e03 100644 --- a/rsocket/src/payload/normal.rs +++ b/rsocket/src/payload/normal.rs @@ -64,17 +64,11 @@ impl Payload { } pub fn metadata(&self) -> Option<&Bytes> { - match &self.m { - Some(b) => Some(b), - None => None, - } + self.m.as_ref() } pub fn data(&self) -> Option<&Bytes> { - match &self.d { - Some(b) => Some(b), - None => None, - } + self.d.as_ref() } pub fn data_utf8(&self) -> Option<&str> { diff --git a/rsocket/src/payload/setup.rs b/rsocket/src/payload/setup.rs index e882b74..7ce4057 100644 --- a/rsocket/src/payload/setup.rs +++ b/rsocket/src/payload/setup.rs @@ -100,17 +100,11 @@ impl SetupPayloadBuilder { impl SetupPayload { pub fn metadata(&self) -> Option<&Bytes> { - match &self.m { - Some(b) => Some(b), - None => None, - } + self.m.as_ref() } pub fn data(&self) -> Option<&Bytes> { - match &self.d { - Some(b) => Some(b), - None => None, - } + self.d.as_ref() } pub fn split(self) -> (Option, Option) { From 5e4b5b2eb6507c1c31a5540187c051a21914569f Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Wed, 30 Dec 2020 23:57:54 +0800 Subject: [PATCH 38/70] feat(request_response): handle empty response correctly --- rsocket-messaging/src/requester.rs | 9 +++++--- rsocket-transport-wasm/src/misc.rs | 3 ++- rsocket/src/core/client.rs | 2 +- rsocket/src/spi.rs | 2 +- rsocket/src/transport/socket.rs | 35 +++++++++++++++++++++--------- rsocket/src/utils.rs | 6 ++--- 6 files changed, 38 insertions(+), 19 deletions(-) diff --git a/rsocket-messaging/src/requester.rs b/rsocket-messaging/src/requester.rs index 435e08e..65dca41 100644 --- a/rsocket-messaging/src/requester.rs +++ b/rsocket-messaging/src/requester.rs @@ -15,7 +15,7 @@ use url::Url; type FnMetadata = Box Result<(MimeType, Vec)>>; type FnData = Box Result>>; type PreflightResult = Result<(Payload, MimeType, Arc>)>; -type UnpackerResult = Result<(MimeType, Payload)>; +type UnpackerResult = Result<(MimeType, Option)>; type UnpackersResult = Result<(MimeType, Flux>)>; enum TransportKind { @@ -352,8 +352,11 @@ impl Unpacker { T: Sized + DeserializeOwned, { let (mime_type, inner) = self.inner?; - match inner.data() { - Some(raw) => do_unmarshal(&mime_type, raw), + match inner { + Some(it) => match it.data() { + Some(raw) => do_unmarshal(&mime_type, raw), + None => Ok(None), + }, None => Ok(None), } } diff --git a/rsocket-transport-wasm/src/misc.rs b/rsocket-transport-wasm/src/misc.rs index 96d1dcb..48b6a73 100644 --- a/rsocket-transport-wasm/src/misc.rs +++ b/rsocket-transport-wasm/src/misc.rs @@ -73,10 +73,11 @@ impl JsClient { let request: JsPayload = request.into_serde().unwrap(); future_to_promise(async move { match inner.request_response(request.into()).await { - Ok(v) => { + Ok(Some(v)) => { let jp = JsPayload::from(v); Ok((&jp).into()) } + Ok(None) => Ok(JsValue::UNDEFINED), Err(e) => Err(JsValue::from(&format!("{:?}", e))), } }) diff --git a/rsocket/src/core/client.rs b/rsocket/src/core/client.rs index 3cd5f99..29a92d2 100644 --- a/rsocket/src/core/client.rs +++ b/rsocket/src/core/client.rs @@ -217,7 +217,7 @@ impl RSocket for Client { self.socket.fire_and_forget(req).await } - async fn request_response(&self, req: Payload) -> Result { + async fn request_response(&self, req: Payload) -> Result> { self.socket.request_response(req).await } diff --git a/rsocket/src/spi.rs b/rsocket/src/spi.rs index dcae07e..1d2a805 100644 --- a/rsocket/src/spi.rs +++ b/rsocket/src/spi.rs @@ -18,7 +18,7 @@ pub type Flux = Pin>>; pub trait RSocket: Sync + Send { async fn metadata_push(&self, req: Payload) -> Result<()>; async fn fire_and_forget(&self, req: Payload) -> Result<()>; - async fn request_response(&self, req: Payload) -> Result; + async fn request_response(&self, req: Payload) -> Result>; fn request_stream(&self, req: Payload) -> Flux>; fn request_channel(&self, reqs: Flux>) -> Flux>; } diff --git a/rsocket/src/transport/socket.rs b/rsocket/src/transport/socket.rs index 9d08570..007a37b 100644 --- a/rsocket/src/transport/socket.rs +++ b/rsocket/src/transport/socket.rs @@ -36,7 +36,7 @@ struct Responder { #[derive(Debug)] enum Handler { - ReqRR(oneshot::Sender>), + ReqRR(oneshot::Sender>>), ResRR(Counter), ReqRS(mpsc::Sender>), ReqRC(mpsc::Sender>), @@ -261,12 +261,12 @@ impl DuplexSocket { // pick handler if let Some((_, handler)) = self.handlers.remove(&sid) { let desc = input.get_data_utf8().unwrap().to_owned(); - let e: Result<_> = Err(RSocketError::must_new_from_code(input.get_code(), desc).into()); + let e = RSocketError::must_new_from_code(input.get_code(), desc); match handler { - Handler::ReqRR(tx) => tx.send(e).expect("Send RR failed"), + Handler::ReqRR(tx) => tx.send(Err(e.into())).expect("Send RR failed"), Handler::ResRR(_) => unreachable!(), - Handler::ReqRS(tx) => tx.send(e).await.expect("Send RS failed"), - Handler::ReqRC(tx) => tx.send(e).await.expect("Send RC failed"), + Handler::ReqRS(tx) => tx.send(Err(e.into())).await.expect("Send RS failed"), + Handler::ReqRC(tx) => tx.send(Err(e.into())).await.expect("Send RC failed"), } } } @@ -303,7 +303,11 @@ impl DuplexSocket { match o.get() { Handler::ReqRR(_) => match o.remove() { Handler::ReqRR(sender) => { - sender.send(Ok(input)).unwrap(); + if flag & Frame::FLAG_NEXT != 0 { + sender.send(Ok(Some(input))).unwrap(); + } else { + sender.send(Ok(None)).unwrap(); + } } _ => unreachable!(), }, @@ -394,7 +398,7 @@ impl DuplexSocket { canceller.send(sid).await.expect("Send canceller failed"); match result { - Ok(res) => { + Ok(Some(res)) => { Self::try_send_payload( &splitter, &mut tx, @@ -404,6 +408,9 @@ impl DuplexSocket { ) .await; } + Ok(None) => { + Self::try_send_complete(&mut tx, sid, Frame::FLAG_COMPLETE).await; + } Err(e) => { let sending = frame::Error::builder(sid, 0) .set_code(error::ERR_APPLICATION) @@ -570,6 +577,14 @@ impl DuplexSocket { } } + #[inline] + async fn try_send_complete(tx: &mut mpsc::Sender, sid: u32, flag: u16) { + let sending = frame::Payload::builder(sid, flag).build(); + if let Err(e) = tx.send(sending).await { + error!("respond failed: {}", e); + } + } + #[inline] async fn try_send_payload( splitter: &Option, @@ -697,8 +712,8 @@ impl RSocket for DuplexSocket { Ok(()) } - async fn request_response(&self, req: Payload) -> Result { - let (tx, rx) = oneshot::channel::>(); + async fn request_response(&self, req: Payload) -> Result> { + let (tx, rx) = oneshot::channel::>>(); let sid = self.seq.next(); let handlers = self.handlers.clone(); let sender = self.tx.clone(); @@ -911,7 +926,7 @@ impl RSocket for Responder { (*inner).fire_and_forget(req).await } - async fn request_response(&self, req: Payload) -> Result { + async fn request_response(&self, req: Payload) -> Result> { let inner = self.inner.read().await; (*inner).request_response(req).await } diff --git a/rsocket/src/utils.rs b/rsocket/src/utils.rs index 2cec431..5cbc589 100644 --- a/rsocket/src/utils.rs +++ b/rsocket/src/utils.rs @@ -26,9 +26,9 @@ impl RSocket for EchoRSocket { Ok(()) } - async fn request_response(&self, req: Payload) -> Result { + async fn request_response(&self, req: Payload) -> Result> { info!("{:?}", req); - Ok(req) + Ok(Some(req)) } fn request_stream(&self, req: Payload) -> Flux> { @@ -67,7 +67,7 @@ impl RSocket for EmptyRSocket { Err(RSocketError::ApplicationException("UNIMPLEMENT".into()).into()) } - async fn request_response(&self, _req: Payload) -> Result { + async fn request_response(&self, _req: Payload) -> Result> { Err(RSocketError::ApplicationException("UNIMPLEMENT".into()).into()) } From 65b3900227b4280507557a801f4abfed993c340c Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Tue, 5 Jan 2021 22:36:03 +0800 Subject: [PATCH 39/70] feat: implment tls transport (#31) * feat: implement tls transport based on tokio-native-tls * feat: add wait_for_close for client --- examples/Cargo.toml | 10 ++- examples/tls/cert.pem | 31 +++++++++ examples/tls/client.rs | 35 ++++++++++ examples/tls/identity.p12 | Bin 0 -> 4117 bytes examples/tls/server.rs | 27 ++++++++ rsocket-transport-tcp/Cargo.toml | 9 ++- rsocket-transport-tcp/src/client/mod.rs | 4 ++ rsocket-transport-tcp/src/client/tcp.rs | 2 +- rsocket-transport-tcp/src/client/tls.rs | 50 ++++++++++++++ rsocket-transport-tcp/src/client/uds.rs | 2 +- rsocket-transport-tcp/src/connection/mod.rs | 4 ++ rsocket-transport-tcp/src/connection/tcp.rs | 2 +- rsocket-transport-tcp/src/connection/tls.rs | 64 ++++++++++++++++++ rsocket-transport-tcp/src/connection/uds.rs | 2 +- rsocket-transport-tcp/src/lib.rs | 9 +++ rsocket-transport-tcp/src/server/mod.rs | 5 ++ rsocket-transport-tcp/src/server/tcp.rs | 7 +- rsocket-transport-tcp/src/server/tls.rs | 57 ++++++++++++++++ rsocket-transport-tcp/src/server/uds.rs | 2 +- rsocket-transport-websocket/Cargo.toml | 1 - rsocket-transport-websocket/src/client.rs | 3 +- rsocket-transport-websocket/src/connection.rs | 2 +- rsocket-transport-websocket/src/server.rs | 3 +- rsocket/Cargo.toml | 4 +- rsocket/src/core/client.rs | 42 ++++++++---- rsocket/src/core/factory.rs | 4 +- rsocket/src/core/server.rs | 20 +++--- rsocket/src/lib.rs | 5 ++ rsocket/src/spi.rs | 48 +++++++++++-- rsocket/src/transport/misc.rs | 9 +-- rsocket/src/utils.rs | 14 ++-- scripts/generate-certificate.sh | 59 ++++++++++++++++ 32 files changed, 472 insertions(+), 64 deletions(-) create mode 100644 examples/tls/cert.pem create mode 100644 examples/tls/client.rs create mode 100644 examples/tls/identity.p12 create mode 100644 examples/tls/server.rs create mode 100644 rsocket-transport-tcp/src/client/tls.rs create mode 100644 rsocket-transport-tcp/src/connection/tls.rs create mode 100644 rsocket-transport-tcp/src/server/tls.rs create mode 100755 scripts/generate-certificate.sh diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 135fbb7..483cc67 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -10,13 +10,13 @@ log = "0.4.11" env_logger = "0.8.2" futures = "0.3.8" clap = "2.33.3" -async-trait = "0.1.42" [dev-dependencies.rsocket_rust] path = "../rsocket" [dev-dependencies.rsocket_rust_transport_tcp] path = "../rsocket-transport-tcp" +features = ["tls"] [dev-dependencies.rsocket_rust_transport_websocket] path = "../rsocket-transport-websocket" @@ -41,3 +41,11 @@ path = "cli.rs" [[example]] name = "qps" path = "qps.rs" + +[[example]] +name = "tls-server" +path = "tls/server.rs" + +[[example]] +name = "tls-client" +path = "tls/client.rs" \ No newline at end of file diff --git a/examples/tls/cert.pem b/examples/tls/cert.pem new file mode 100644 index 0000000..20ad7d4 --- /dev/null +++ b/examples/tls/cert.pem @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFUDCCAzigAwIBAgIJAJjWP27hY7PeMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQwHhcNMjEwMTA1MDMwODUzWhcNMjIwMTA1MDMwODUzWjBa +MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 +ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRMwEQYDVQQDDApmb29iYXIuY29tMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtv10GWc14Kyu94jmT/a52HEdTf9f +gSFc9fTiGIcvsHwGe5HU5tMEEpVmVQqMeWHMgIunHpAVbmu9dhZ/r256QiR+bU8o +Zzv6ShJ6gdYAv/j2MEu7sHFpFHWEaZmPgqbREHioerS8AMJwNLcFF47EKUsKlbJy +Yn7rsfDl1Vir3I5l2VOORmjNOap/++CNJf39oGN8yx6+6YUT+lcUY2GkI8BkXLRI +ITTYOnAsjnwtk9k2sHQaCMfmlQYr5FCDTi2A4MEWfBecJ8Logbt+E02ZaaMj5pSW +Q4oqpZUEzhYhUgNUahy1Gfeso9BZsFj056dn8qiaa61tV1vtFsnk2bHEU9HTu/NA +TwTLsRhWVqfOA04zT2V9OPcaO+shiMsY7JzivLFnBBsPeTC43e5Js1OZSeRr6Dbq +8jJ61p+f5DbBRHUFl3oZ0pz+8xYpusDHHzVPqE5izKS3fz2FNyK+OjJwEsNmSpNc +X4+g3YeZj3Oq4fs/vGu3y1IZq9wIR1pBSRosW+SOpPd9PBWhbF43fUa0k2kSI7Xc +BkDQbEWxY0jEY4vzvNOA2C5A3eg8DzvDpjGE13GeSzk3DsObwmugHWZaz/TK0KeI +7LWDCHkUBizublZ+htUHDZxTU5mXWhaU2tU/udz+4rPVymns8RZ+Omm3uOC4PuQo +g+ezrcaZwyZptv0CAwEAAaMuMCwwEwYDVR0lBAwwCgYIKwYBBQUHAwEwFQYDVR0R +BA4wDIIKZm9vYmFyLmNvbTANBgkqhkiG9w0BAQsFAAOCAgEAKj6H77fLp5jL/oEJ +qglaOaM4OHU4FbQ3mTPLTjeVrvcnoxavigZC++0FwEkNm9FEfA8fDDNsVgK4CTof +Jdsq10hkHVE44Y5WLJha4o50dvUczj0k4wV5BaZ0cC2aYwdRXVkSYVNa90951pDq +FBy75ltWUWnQ8tibU4tZPgg2sbMzWkcRJ5bJfmEFVbB930x6ofllVZx2h9wZERBp +otgtJzQ1+P+MZ5By2nF59gpKURbRyS06y5emuhs/7UF2E/ETvMTiyBgcRiASYqGO +2bcxvZ6J6zo93D2gEAUKrP2QVsE0o3oTtc3N5ix1lXegdi9AM4AGnzb8uDkjyJHn +J9ibW1pWPYey2DjArbcq1uSKzXtC+YVEdS7k6X91ksYrFZgjAporyhJbqISq+sJO +1gaTXu1VRNRhFVfJQjNVfA0ar+RHcx5xetdJKRglekGqGcBQfTFMNhLcGfuY16pe +qRzF9gwCqnX0c+tIl32IxCS4g6Pj/LBn3qCGE4sycWUz6+mwjGopFWK2gBGpj4M0 +Dvnv+c72QQKmijtpQX6tSn75MBhtG9hZD8jPpMyfIFfkhx71StZ4j1O+rvXQs7go +Nb9qJOug/jfSrDQl9D5FSlRaqX19fm7JxiK7+fSnh/WlMmBQfn/j/lJ/sSDcyAbb +KrQM79kml5Luw0QXo7yLtoYD93A= +-----END CERTIFICATE----- diff --git a/examples/tls/client.rs b/examples/tls/client.rs new file mode 100644 index 0000000..6744a4b --- /dev/null +++ b/examples/tls/client.rs @@ -0,0 +1,35 @@ +#[macro_use] +extern crate log; + +use rsocket_rust::prelude::*; +use rsocket_rust::Result; +use rsocket_rust_transport_tcp::tokio_native_tls::{native_tls, TlsConnector}; +use rsocket_rust_transport_tcp::TlsClientTransport; + +#[tokio::main] +async fn main() -> Result<()> { + env_logger::builder().format_timestamp_millis().init(); + + let pem = include_bytes!("cert.pem"); + let cert = native_tls::Certificate::from_pem(pem)?; + let cx = native_tls::TlsConnector::builder() + .add_root_certificate(cert) + .build()?; + let cx = TlsConnector::from(cx); + let cli = RSocketFactory::connect() + .transport(TlsClientTransport::new( + "foobar.com".into(), + "127.0.0.1:4444".parse()?, + cx, + )) + .start() + .await?; + let res = cli + .request_response(Payload::builder().set_data_utf8("hello").build()) + .await?; + info!("response: {:?}", res); + + cli.wait_for_close().await; + + Ok(()) +} diff --git a/examples/tls/identity.p12 b/examples/tls/identity.p12 new file mode 100644 index 0000000000000000000000000000000000000000..b0c9e5e5d9977157970bc9aeba885e75e0233a4c GIT binary patch literal 4117 zcmY+GWmFUlw}lycn4m*ay1Q{m>6Q|u8-`(!msAkxp@t3-fsq(ON@V~+T0&B~Q@SK2 z6u7=?-Fv@#f1GvJdiFZ!=iXZ^f`SqsKp+-DK1~c1h|!L@fB;AUmRC9*0D)i&ylj4O%5Y_5{ zcT0p!^!({_MaZHbsSh9Y>)}?6IM&ZSxHR@?i};Yj05$F~eIyO)OjNSLD~#x+D=9?R ze}t_-bb~A1x!5*Qi7|c>RVm78Lg>VE7zpLT#>sP^c2M)BK)W#@U3p4AFI9qNI~hS` z=Uf50g1{R2Q~vmD&VFQY^g!TR?C)7L_iV}id>xj46*bd^p!MqEJI?e!QFmi);$k?3 zd8)4_ArH5|7oHjSkyc{I54S%rgi?%4W_SzlN>udxGei~K25x-M%8@n!(1q^sEBr9B zlP-7T7x8YrF}Q_AX1+0aZy?p`p>U8Q$ph}j zqMCIQ@Ts`$`;OXPuO3Jk^9bG#mJvJ9=fUU1$eyiYhi>Cnl`(ZcH&&n3>Lxfr@R@>2 zV}KtvH4J@_tMbwJ6YWW9i>5EQi0vzOEXaKXwRsZiZ$isLE#IQ;(*_CX-3VeJ2nD<# zDa+nz^+kRq4sOV{j6uDv@Ox=-ozbfoVZ2VwtZsSAHBWT4#ch%X-}*}=$MAP9<5iV` z%YVS0e~)f{Kq1ZUE#2`>_wi+_^2>=8#|3UYA_UhR&Mjz#gVmMfXgc|@fZ1tnCrzw- zo_d5gzk9;bEo)ClfPGA&&-X55W~IWr*Z!p|KDcwd16?U)6dHE8ux_zoH1S*)uW-Tv zAsusX37YIB^vxOnbC(fg!jH`3ujCdzpjJ{Yn2W#Av z2yhtv9%x8F^lp#T6YLA}9@Z%x^ux7WSiZ9%c*>b?Gj`V*2^iUwr2oW|=qE<7nfATn zdB45zysavog;1cgmd$~0-Iynl&*YpsOy?Et4Ap54JVP5v!qin#Yo@3q!73U^TKEoj zu?t^2SqhJsw>LqA+uqS>I@kZW=&@Lw0?Fkg%`(my&;KX~Ks9wBgc}ufE!1|A9hK2; zn7)|I)L2KtF*z~tf>IW+QSy`oK}{EXGI#rU_9PxXGG7V#cm|WRs5j1*ACE3+8H}D>;c$6@B67oG>lwB_jlRYP(-5Aq1|zvTkl>N3XFw z0edd`*vp5UfQ$laTLk^n^TKP&{WyB3SD4rZXzvVRiW?tdA6#qQlCOpFJG8r79jol%Hs2 z?cG$VWJ8eOWsdJpp>D0rDZ(x;tSod0OP;*KX$pY&k>iiHjEa4Ldw>0^y+ib>~@Q$HKhj%SZ0j6 zj=DMHKY36-pUXg${gY^3(1c7;n}rT?vM+DiS-6sAW4YC#8U&Yn5`{BdV$Ka&9Y-Mm zkF+S=l-NS&kQT%Z;e#6g8JVlsSi~_P>0K9=$gXr<~l9 zrDS9|XJ~-5083Q7CUq3Bi$F51vXb$@dq^g?81M3d7&I^R(^F#`g$V z{s4p!7gggTjxURbA0h1NANf+o3^3Tq^WN)jRY&dS3Wee?FjqGkB>649R%mfoA-C;c zaNv&6v1w(P#b8<2Y8vUt;lPNvQED*)f;U$o$U5Vf?TF=2i8TEH!|*hZ&`x9A0VU5y z)w*6&zeBQ%3^1g5zfY2mvU(3)82BMkIPu&ggA;41`9Qa#c`(X8%ylx38(Vi7JVbvcQJ{Y~{NA_%|`!S1o{flNbdHb?81eK9W|wa%u=*?e^)bQ%l-JG~C6- zoZj%0?+qj>M)pX3*B|EBfu~b)1$k26Z6iu47aj-~uSO!13*O92XarZ|^7T=-%Zyl!sn=9ucc(c?~yx4-A<1Plz84U4((Hr~@uA9@MDy$3;+nIBQ&^QjKIxR2JC1 z5P9CxV;6W-wL}rnivkjQprN$ep}|}HRN29?WI${0T0Iv2N(IPQv#N^&96J-P>Zd(i zGb=Duyo%?8DSMNg{HW)rupuS#9Jd%{pl1%1&Md3J`lpGd&;%JYw73Y++PWvrNm{as z3zXI~u=!$^NIbbuiwYfWb*OS0J0UO!two(zP>t0nsTn4!8)n1F-e+O3{n@=j|0r5o z1qHxP1hB~_;kP&Wg;__<5@v25#(ceeEm>Aa_v+W&)?Y+OD_p1(2#>qWYchMvg3i7P zinzi8)CowlXSXKzmx-b@R97suIELpFbqjl`YDcOdu`9i_RY-WDL-0^1M~_*-XGNkn zJzn}OF<*SALgE@{A2wU-QWbS;9fqaJd>r>AcV}45KwV+{)xsk%b}32ZR% z3Kh3wHT-Z6YfAEMk1?ueOa6E#GS+4^nNgAmG^lztm^#B}EI}2&%F81+CF~gt!%7@e zw6k8bQfWs<`V%GW_Pxe)4~sJ@g9N+xB5#@tF2}$U<%P#mG}U~di+-6sWx1m}6SgPu z;Ml{-@ZQQPC!My;9g7cjOP`CZQeBtR%bq~jE>z)lVzq4R5^A5w0^W?dQfSakz+@Vl z92iSX)$|IRZ{IW})o==}zK}IyOy&P>wK-oB9aj}G*veH-*i`U7S!r^Qek$oabGr(pViX_8UWYz z`ANd!^|%irxTNXouKe_vLB-(N_VBA0v0gm(kDt@Oz!RK#zU-jOO%%Xtxdb8UwDtSp zJKH0zp;!d)nG!pqm@KkLp za~OX6+;cIG;RJC=Kuc35n0+ce7j3c06^@h70Z{k(WcTYi=Nn7!MCvZLf9LSyzs?Uc7I>`*>WwlI=eHy?WE5Ys1?`5Y z8v;m?S@Fh38KHd8k?aa2WvV&LwUuqlseazK#8thp&8PZ3xns7ZTPn>vMO`0Xe@9D& zJTTM2rOez}?AyYlzW`Cf_+ZNeEiQu_y+$(=tz{~WEK;W(vgEhy1KkB&co+kZP6*Qs zPm3C;y#YF#@8^!t^JicusuKm zPsA=QsdI&S0(V$f_qjPdsDm$_-up?%c7Cp=dWmL=GnfnaeRSwP6DOF@z7@49R?868 z4DRVz&>jq$bx>mD8GyiRA{{>lrk#_(9 literal 0 HcmV?d00001 diff --git a/examples/tls/server.rs b/examples/tls/server.rs new file mode 100644 index 0000000..28d5544 --- /dev/null +++ b/examples/tls/server.rs @@ -0,0 +1,27 @@ +#[macro_use] +extern crate log; + +use rsocket_rust::prelude::*; +use rsocket_rust::utils::EchoRSocket; +use rsocket_rust::Result; +use rsocket_rust_transport_tcp::tokio_native_tls::{native_tls, TlsAcceptor}; +use rsocket_rust_transport_tcp::TlsServerTransport; + +#[tokio::main] +async fn main() -> Result<()> { + env_logger::builder().format_timestamp_millis().init(); + + let der = include_bytes!("identity.p12"); + let cert = native_tls::Identity::from_pkcs12(der, "mypass")?; + RSocketFactory::receive() + .acceptor(Box::new(|setup, _socket| { + info!("connection established: {:?}", setup); + Ok(Box::new(EchoRSocket)) + })) + .transport(TlsServerTransport::new( + "127.0.0.1:4444".parse()?, + TlsAcceptor::from(native_tls::TlsAcceptor::builder(cert).build()?), + )) + .serve() + .await +} diff --git a/rsocket-transport-tcp/Cargo.toml b/rsocket-transport-tcp/Cargo.toml index 7895836..589fe31 100644 --- a/rsocket-transport-tcp/Cargo.toml +++ b/rsocket-transport-tcp/Cargo.toml @@ -9,11 +9,14 @@ repository = "https://github.com/rsocket/rsocket-rust" homepage = "https://github.com/rsocket/rsocket-rust" description = "TCP RSocket transport implementation." +[features] +default = [] +tls = ["tokio-native-tls"] + [dependencies] log = "0.4.11" futures = "0.3.8" bytes = "0.6.0" -async-trait = "0.1.42" [dependencies.rsocket_rust] path = "../rsocket" @@ -28,3 +31,7 @@ features = [ "rt", "rt-multi-thread", "net", "sync", "stream", "io-util", "macro version = "0.5.1" default-features = false features = ["codec"] + +[dependencies.tokio-native-tls] +optional = true +version = "0.2.0" diff --git a/rsocket-transport-tcp/src/client/mod.rs b/rsocket-transport-tcp/src/client/mod.rs index 6159817..f0f1acd 100644 --- a/rsocket-transport-tcp/src/client/mod.rs +++ b/rsocket-transport-tcp/src/client/mod.rs @@ -1,5 +1,9 @@ mod tcp; +#[cfg(feature = "tls")] +mod tls; mod uds; pub use tcp::TcpClientTransport; +#[cfg(feature = "tls")] +pub use tls::TlsClientTransport; pub use uds::UnixClientTransport; diff --git a/rsocket-transport-tcp/src/client/tcp.rs b/rsocket-transport-tcp/src/client/tcp.rs index 4d3e0b0..9896dbe 100644 --- a/rsocket-transport-tcp/src/client/tcp.rs +++ b/rsocket-transport-tcp/src/client/tcp.rs @@ -1,5 +1,5 @@ use crate::{connection::TcpConnection, misc::parse_tcp_addr}; -use async_trait::async_trait; +use rsocket_rust::async_trait; use rsocket_rust::{error::RSocketError, transport::Transport, Result}; use std::net::SocketAddr; use tokio::net::TcpStream; diff --git a/rsocket-transport-tcp/src/client/tls.rs b/rsocket-transport-tcp/src/client/tls.rs new file mode 100644 index 0000000..3bc21a1 --- /dev/null +++ b/rsocket-transport-tcp/src/client/tls.rs @@ -0,0 +1,50 @@ +use crate::connection::TlsConnection; +use rsocket_rust::async_trait; +use rsocket_rust::{error::RSocketError, transport::Transport, Result}; +use std::net::SocketAddr; +use tokio::net::TcpStream; +use tokio_native_tls::{TlsConnector, TlsStream}; + +#[derive(Debug)] +enum Connector { + Direct(TlsStream), + Lazy(String, SocketAddr, TlsConnector), +} + +pub struct TlsClientTransport { + connector: Connector, +} + +impl TlsClientTransport { + pub fn new(domain: String, addr: SocketAddr, connector: TlsConnector) -> Self { + Self { + connector: Connector::Lazy(domain, addr, connector), + } + } +} + +#[async_trait] +impl Transport for TlsClientTransport { + type Conn = TlsConnection; + + async fn connect(self) -> Result { + match self.connector { + Connector::Direct(stream) => Ok(TlsConnection::from(stream)), + Connector::Lazy(domain, addr, cx) => match TcpStream::connect(addr).await { + Ok(stream) => match cx.connect(&domain, stream).await { + Ok(stream) => Ok(TlsConnection::from(stream)), + Err(e) => Err(RSocketError::Other(e.into()).into()), + }, + Err(e) => Err(RSocketError::IO(e).into()), + }, + } + } +} + +impl From> for TlsClientTransport { + fn from(stream: TlsStream) -> Self { + Self { + connector: Connector::Direct(stream), + } + } +} diff --git a/rsocket-transport-tcp/src/client/uds.rs b/rsocket-transport-tcp/src/client/uds.rs index 749bf8f..1efd9f3 100644 --- a/rsocket-transport-tcp/src/client/uds.rs +++ b/rsocket-transport-tcp/src/client/uds.rs @@ -1,6 +1,6 @@ use crate::connection::UnixConnection; use crate::misc::parse_uds_addr; -use async_trait::async_trait; +use rsocket_rust::async_trait; use rsocket_rust::{error::RSocketError, transport::Transport, Result}; use tokio::net::UnixStream; diff --git a/rsocket-transport-tcp/src/connection/mod.rs b/rsocket-transport-tcp/src/connection/mod.rs index de8846d..8df67b6 100644 --- a/rsocket-transport-tcp/src/connection/mod.rs +++ b/rsocket-transport-tcp/src/connection/mod.rs @@ -1,6 +1,10 @@ mod codec; mod tcp; +#[cfg(feature = "tls")] +mod tls; mod uds; pub use tcp::TcpConnection; +#[cfg(feature = "tls")] +pub use tls::TlsConnection; pub use uds::UnixConnection; diff --git a/rsocket-transport-tcp/src/connection/tcp.rs b/rsocket-transport-tcp/src/connection/tcp.rs index 456a5c9..00252f3 100644 --- a/rsocket-transport-tcp/src/connection/tcp.rs +++ b/rsocket-transport-tcp/src/connection/tcp.rs @@ -1,7 +1,7 @@ use super::codec::LengthBasedFrameCodec; -use async_trait::async_trait; use futures::stream::{SplitSink, SplitStream}; use futures::{SinkExt, StreamExt}; +use rsocket_rust::async_trait; use rsocket_rust::frame::Frame; use rsocket_rust::transport::{Connection, Reader, Writer}; use rsocket_rust::{error::RSocketError, Result}; diff --git a/rsocket-transport-tcp/src/connection/tls.rs b/rsocket-transport-tcp/src/connection/tls.rs new file mode 100644 index 0000000..b2041c7 --- /dev/null +++ b/rsocket-transport-tcp/src/connection/tls.rs @@ -0,0 +1,64 @@ +use super::codec::LengthBasedFrameCodec; +use futures::stream::{SplitSink, SplitStream}; +use futures::{SinkExt, StreamExt}; +use rsocket_rust::async_trait; +use rsocket_rust::frame::Frame; +use rsocket_rust::transport::{Connection, Reader, Writer}; +use rsocket_rust::{error::RSocketError, Result}; +use tokio::net::TcpStream; +use tokio_native_tls::TlsStream; +use tokio_util::codec::Framed; + +#[derive(Debug)] +pub struct TlsConnection { + stream: TlsStream, +} + +struct InnerWriter { + sink: SplitSink, LengthBasedFrameCodec>, Frame>, +} + +struct InnerReader { + stream: SplitStream, LengthBasedFrameCodec>>, +} + +#[async_trait] +impl Writer for InnerWriter { + async fn write(&mut self, frame: Frame) -> Result<()> { + match self.sink.send(frame).await { + Ok(()) => Ok(()), + Err(e) => Err(RSocketError::IO(e).into()), + } + } +} + +#[async_trait] +impl Reader for InnerReader { + async fn read(&mut self) -> Option> { + self.stream + .next() + .await + .map(|next| next.map_err(|e| RSocketError::IO(e).into())) + } +} + +impl Connection for TlsConnection { + fn split( + self, + ) -> ( + Box, + Box, + ) { + let (sink, stream) = Framed::new(self.stream, LengthBasedFrameCodec).split(); + ( + Box::new(InnerWriter { sink }), + Box::new(InnerReader { stream }), + ) + } +} + +impl From> for TlsConnection { + fn from(stream: TlsStream) -> Self { + Self { stream } + } +} diff --git a/rsocket-transport-tcp/src/connection/uds.rs b/rsocket-transport-tcp/src/connection/uds.rs index 4050cf7..f62e831 100644 --- a/rsocket-transport-tcp/src/connection/uds.rs +++ b/rsocket-transport-tcp/src/connection/uds.rs @@ -1,7 +1,7 @@ use super::codec::LengthBasedFrameCodec; -use async_trait::async_trait; use futures::stream::{SplitSink, SplitStream}; use futures::{SinkExt, StreamExt}; +use rsocket_rust::async_trait; use rsocket_rust::frame::Frame; use rsocket_rust::transport::{Connection, Reader, Writer}; use rsocket_rust::{error::RSocketError, Result}; diff --git a/rsocket-transport-tcp/src/lib.rs b/rsocket-transport-tcp/src/lib.rs index ab1a824..50b535e 100644 --- a/rsocket-transport-tcp/src/lib.rs +++ b/rsocket-transport-tcp/src/lib.rs @@ -11,3 +11,12 @@ mod server; pub use client::{TcpClientTransport, UnixClientTransport}; pub use connection::{TcpConnection, UnixConnection}; pub use server::{TcpServerTransport, UnixServerTransport}; + +#[cfg(feature = "tls")] +pub use client::TlsClientTransport; +#[cfg(feature = "tls")] +pub use connection::TlsConnection; +#[cfg(feature = "tls")] +pub use server::TlsServerTransport; +#[cfg(feature = "tls")] +pub use tokio_native_tls; diff --git a/rsocket-transport-tcp/src/server/mod.rs b/rsocket-transport-tcp/src/server/mod.rs index 2adea25..1dda335 100644 --- a/rsocket-transport-tcp/src/server/mod.rs +++ b/rsocket-transport-tcp/src/server/mod.rs @@ -1,5 +1,10 @@ mod tcp; + +#[cfg(feature = "tls")] +mod tls; mod uds; pub use tcp::TcpServerTransport; +#[cfg(feature = "tls")] +pub use tls::TlsServerTransport; pub use uds::UnixServerTransport; diff --git a/rsocket-transport-tcp/src/server/tcp.rs b/rsocket-transport-tcp/src/server/tcp.rs index e15e5cf..0ab415e 100644 --- a/rsocket-transport-tcp/src/server/tcp.rs +++ b/rsocket-transport-tcp/src/server/tcp.rs @@ -1,5 +1,5 @@ use crate::{client::TcpClientTransport, misc::parse_tcp_addr}; -use async_trait::async_trait; +use rsocket_rust::async_trait; use rsocket_rust::{error::RSocketError, transport::ServerTransport, Result}; use std::net::SocketAddr; use tokio::net::TcpListener; @@ -40,10 +40,7 @@ impl ServerTransport for TcpServerTransport { async fn next(&mut self) -> Option> { match self.listener.as_mut() { Some(listener) => match listener.accept().await { - Ok((socket, _)) => { - let tp = TcpClientTransport::from(socket); - Some(Ok(tp)) - } + Ok((socket, _)) => Some(Ok(TcpClientTransport::from(socket))), Err(e) => Some(Err(RSocketError::IO(e).into())), }, None => None, diff --git a/rsocket-transport-tcp/src/server/tls.rs b/rsocket-transport-tcp/src/server/tls.rs new file mode 100644 index 0000000..b92f3b8 --- /dev/null +++ b/rsocket-transport-tcp/src/server/tls.rs @@ -0,0 +1,57 @@ +use crate::client::TlsClientTransport; +use rsocket_rust::async_trait; +use rsocket_rust::{error::RSocketError, transport::ServerTransport, Result}; +use std::net::SocketAddr; +use tokio::net::TcpListener; +use tokio_native_tls::TlsAcceptor; + +pub struct TlsServerTransport { + addr: SocketAddr, + listener: Option, + tls_acceptor: TlsAcceptor, +} + +impl TlsServerTransport { + pub fn new(addr: SocketAddr, tls_acceptor: TlsAcceptor) -> Self { + Self { + addr, + listener: None, + tls_acceptor, + } + } +} + +#[async_trait] +impl ServerTransport for TlsServerTransport { + type Item = TlsClientTransport; + + async fn start(&mut self) -> Result<()> { + if self.listener.is_some() { + return Ok(()); + } + match TcpListener::bind(self.addr).await { + Ok(listener) => { + self.listener = Some(listener); + debug!("listening on: {}", &self.addr); + Ok(()) + } + Err(e) => Err(RSocketError::IO(e).into()), + } + } + + async fn next(&mut self) -> Option> { + match self.listener.as_mut() { + Some(listener) => match listener.accept().await { + Ok((socket, _)) => { + let tls_acceptor = self.tls_acceptor.clone(); + match tls_acceptor.accept(socket).await { + Ok(stream) => Some(Ok(TlsClientTransport::from(stream))), + Err(e) => Some(Err(RSocketError::Other(e.into()).into())), + } + } + Err(e) => Some(Err(RSocketError::IO(e).into())), + }, + None => None, + } + } +} diff --git a/rsocket-transport-tcp/src/server/uds.rs b/rsocket-transport-tcp/src/server/uds.rs index a2e1249..24618e2 100644 --- a/rsocket-transport-tcp/src/server/uds.rs +++ b/rsocket-transport-tcp/src/server/uds.rs @@ -1,6 +1,6 @@ use crate::client::UnixClientTransport; use crate::misc::parse_uds_addr; -use async_trait::async_trait; +use rsocket_rust::async_trait; use rsocket_rust::{error::RSocketError, transport::ServerTransport, Result}; use tokio::net::UnixListener; diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index c188373..ca35208 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -15,7 +15,6 @@ futures = "0.3.8" bytes = "0.6.0" url = "2.2.0" tokio-tungstenite = "0.12.0" -async-trait = "0.1.42" [dependencies.rsocket_rust] path = "../rsocket" diff --git a/rsocket-transport-websocket/src/client.rs b/rsocket-transport-websocket/src/client.rs index ead122d..377d61a 100644 --- a/rsocket-transport-websocket/src/client.rs +++ b/rsocket-transport-websocket/src/client.rs @@ -1,6 +1,5 @@ use super::connection::WebsocketConnection; -use async_trait::async_trait; -use rsocket_rust::{error::RSocketError, transport::Transport, Result}; +use rsocket_rust::{async_trait, error::RSocketError, transport::Transport, Result}; use std::net::SocketAddr; use tokio::net::TcpStream; use tokio_tungstenite::{accept_async, connect_async}; diff --git a/rsocket-transport-websocket/src/connection.rs b/rsocket-transport-websocket/src/connection.rs index 503ac78..52fbec9 100644 --- a/rsocket-transport-websocket/src/connection.rs +++ b/rsocket-transport-websocket/src/connection.rs @@ -1,8 +1,8 @@ -use async_trait::async_trait; use bytes::{BufMut, BytesMut}; use futures::stream::{SplitSink, SplitStream}; use futures::{SinkExt, StreamExt}; use rsocket_rust::{ + async_trait, error::RSocketError, frame::Frame, transport::{Connection, Reader, Writer}, diff --git a/rsocket-transport-websocket/src/server.rs b/rsocket-transport-websocket/src/server.rs index 1235300..c77a995 100644 --- a/rsocket-transport-websocket/src/server.rs +++ b/rsocket-transport-websocket/src/server.rs @@ -1,6 +1,5 @@ use super::client::WebsocketClientTransport; -use async_trait::async_trait; -use rsocket_rust::{error::RSocketError, transport::ServerTransport, Result}; +use rsocket_rust::{async_trait, error::RSocketError, transport::ServerTransport, Result}; use std::net::SocketAddr; use tokio::net::TcpListener; diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index fbca125..965f2fc 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -15,8 +15,8 @@ bytes = "0.6.0" futures = "0.3.8" lazy_static = "1.4.0" async-trait = "0.1.42" -dashmap = "3.11.10" -thiserror = "1.0.22" +dashmap = "4.0.1" +thiserror = "1.0.23" anyhow = "1.0.36" async-stream = "0.3.0" diff --git a/rsocket/src/core/client.rs b/rsocket/src/core/client.rs index 29a92d2..da7c686 100644 --- a/rsocket/src/core/client.rs +++ b/rsocket/src/core/client.rs @@ -8,8 +8,8 @@ use crate::transport::{ }; use crate::Result; use async_trait::async_trait; -use futures::{future, select, FutureExt, SinkExt, StreamExt}; -use std::error::Error; +use futures::{future, FutureExt, SinkExt, StreamExt}; +use std::marker::PhantomData; use std::net::SocketAddr; use std::pin::Pin; use std::sync::Arc; @@ -18,25 +18,23 @@ use tokio::sync::{mpsc, Mutex, Notify}; #[derive(Clone)] pub struct Client { + closed: Arc, socket: DuplexSocket, } -pub struct ClientBuilder -where - T: Send + Sync + Transport + 'static, - C: Send + Sync + Connection + 'static, -{ +pub struct ClientBuilder { transport: Option, setup: SetupPayloadBuilder, responder: Option, closer: Option>, mtu: usize, + _c: PhantomData, } impl ClientBuilder where - T: Send + Sync + Transport + 'static, - C: Send + Sync + Connection + 'static, + T: Send + Sync + Transport, + C: Send + Sync + Connection, { pub(crate) fn new() -> ClientBuilder { ClientBuilder { @@ -45,6 +43,7 @@ where setup: SetupPayload::builder(), closer: None, mtu: 0, + _c: PhantomData, } } @@ -105,7 +104,13 @@ where self.closer = Some(callback); self } +} +impl ClientBuilder +where + T: Send + Sync + Transport + 'static, + C: Send + Sync + Connection + 'static, +{ pub async fn start(mut self) -> Result { let tp: T = self.transport.take().expect("missint transport"); @@ -160,6 +165,8 @@ where // begin read loop let closer = self.closer.take(); + let closed = Arc::new(Notify::new()); + let closed_clone = closed.clone(); runtime::spawn(async move { while let Some(next) = stream.read().await { match next { @@ -184,6 +191,9 @@ where debug!("send close notify frame failed!"); } + // notify client closed + closed_clone.notify_one(); + // invoke on_close handler if let Some(mut invoke) = closer { invoke(); @@ -191,17 +201,19 @@ where }); socket.setup(setup).await; - Ok(Client::from(socket)) + Ok(Client::new(socket, closed)) } } -impl From for Client { - fn from(socket: DuplexSocket) -> Client { - Client { socket } +impl Client { + fn new(socket: DuplexSocket, closed: Arc) -> Client { + Client { socket, closed } + } + + pub async fn wait_for_close(self) { + self.closed.notified().await } -} -impl Client { pub fn close(self) { // TODO: support close } diff --git a/rsocket/src/core/factory.rs b/rsocket/src/core/factory.rs index af9445d..cb25f3d 100644 --- a/rsocket/src/core/factory.rs +++ b/rsocket/src/core/factory.rs @@ -15,8 +15,8 @@ impl RSocketFactory { pub fn receive() -> ServerBuilder where - S: Send + Sync + ServerTransport + 'static, - T: Send + Sync + Transport + 'static, + S: Send + Sync + ServerTransport, + T: Send + Sync + Transport, { ServerBuilder::new() } diff --git a/rsocket/src/core/server.rs b/rsocket/src/core/server.rs index d1b03c4..999a9b3 100644 --- a/rsocket/src/core/server.rs +++ b/rsocket/src/core/server.rs @@ -10,26 +10,24 @@ use crate::utils::EmptyRSocket; use crate::Result; use std::error::Error; use std::future::Future; +use std::marker::PhantomData; use std::net::SocketAddr; use std::pin::Pin; use std::sync::Arc; use tokio::sync::mpsc; -pub struct ServerBuilder -where - T: Send + Sync + ServerTransport, - C: Send + Sync + Transport, -{ +pub struct ServerBuilder { transport: Option, on_setup: Option, start_handler: Option>, mtu: usize, + _c: PhantomData, } impl ServerBuilder where - T: Send + Sync + ServerTransport + 'static, - C: Send + Sync + Transport + 'static, + T: Send + Sync + ServerTransport, + C: Send + Sync + Transport, { pub(crate) fn new() -> ServerBuilder { ServerBuilder { @@ -37,9 +35,9 @@ where on_setup: None, start_handler: None, mtu: 0, + _c: PhantomData, } } - pub fn fragment(mut self, mtu: usize) -> Self { if mtu > 0 && mtu < MIN_MTU { panic!("invalid fragment mtu: at least {}!", MIN_MTU) @@ -62,7 +60,13 @@ where self.transport = Some(transport); self } +} +impl ServerBuilder +where + T: Send + Sync + ServerTransport + 'static, + C: Send + Sync + Transport + 'static, +{ pub async fn serve(mut self) -> Result<()> { let mut server_transport = self.transport.take().expect("missing transport"); let acceptor = self.on_setup.map(|v| Acceptor::Generate(Arc::new(v))); diff --git a/rsocket/src/lib.rs b/rsocket/src/lib.rs index 750a0c3..a1703b7 100644 --- a/rsocket/src/lib.rs +++ b/rsocket/src/lib.rs @@ -91,6 +91,11 @@ //! ``` //! +/// A re-export of [`async-stream`](https://docs.rs/async-stream) for creating a Stream. +pub use async_stream::stream; +/// A re-export of [`async-trait`](https://docs.rs/async-trait) for use with RSocket trait implementation. +pub use async_trait::async_trait; + #[macro_use] extern crate log; #[macro_use] diff --git a/rsocket/src/spi.rs b/rsocket/src/spi.rs index 1d2a805..b3b0e6f 100644 --- a/rsocket/src/spi.rs +++ b/rsocket/src/spi.rs @@ -1,12 +1,9 @@ -use crate::error::{self, RSocketError}; use crate::payload::{Payload, SetupPayload}; -use crate::{runtime, Error, Result}; +use crate::Result; use async_trait::async_trait; use futures::Stream; use std::future::Future; use std::pin::Pin; -use std::sync::Arc; -use tokio::sync::mpsc; pub type ClientResponder = Box Box>; pub type ServerResponder = @@ -14,11 +11,54 @@ pub type ServerResponder = pub type Flux = Pin>>; +/// A contract providing different interaction models for RSocket protocol. +/// +/// RSocket trait is based on `async_trait` crate. +/// +/// # Example +/// ``` +/// use rsocket_rust::prelude::*; +/// use rsocket_rust::{async_trait, stream, Result}; +/// +/// struct ExampleRSocket; +/// +/// #[async_trait] +/// impl RSocket for ExampleRSocket { +/// async fn metadata_push(&self, req: Payload) -> Result<()> { +/// Ok(()) +/// } +/// +/// async fn fire_and_forget(&self, req: Payload) -> Result<()> { +/// Ok(()) +/// } +/// +/// async fn request_response(&self, req: Payload) -> Result> { +/// Ok(Some(Payload::builder().set_data_utf8("bingo").build())) +/// } +/// +/// fn request_stream(&self, req: Payload) -> Flux> { +/// Box::pin(stream! { +/// for _ in 0..3 { +/// yield Ok(Payload::builder().set_data_utf8("next payload").build()); +/// } +/// }) +/// } +/// +/// fn request_channel(&self, reqs: Flux>) -> Flux> { +/// reqs +/// } +/// } +/// ``` #[async_trait] pub trait RSocket: Sync + Send { + /// Metadata-Push interaction model of RSocket. async fn metadata_push(&self, req: Payload) -> Result<()>; + /// Fire and Forget interaction model of RSocket. async fn fire_and_forget(&self, req: Payload) -> Result<()>; + /// Request-Response interaction model of RSocket. async fn request_response(&self, req: Payload) -> Result>; + /// Request-Stream interaction model of RSocket. fn request_stream(&self, req: Payload) -> Flux>; + /// Request-Channel interaction model of RSocket. fn request_channel(&self, reqs: Flux>) -> Flux>; } diff --git a/rsocket/src/transport/misc.rs b/rsocket/src/transport/misc.rs index 76e2bf0..7b67b66 100644 --- a/rsocket/src/transport/misc.rs +++ b/rsocket/src/transport/misc.rs @@ -1,13 +1,6 @@ -use crate::error::RSocketError; use crate::frame::Frame; -use crate::payload::{Payload, SetupPayload}; -use crate::spi::RSocket; -use futures::future; -use std::collections::HashMap; -use std::future::Future; use std::sync::atomic::{AtomicI64, AtomicU32, Ordering}; -use std::sync::{Arc, Mutex, RwLock}; -use tokio::sync::oneshot::{self, Receiver, Sender}; +use std::sync::Arc; #[derive(Debug, Clone)] pub(crate) struct StreamID { diff --git a/rsocket/src/utils.rs b/rsocket/src/utils.rs index 5cbc589..1bff3bf 100644 --- a/rsocket/src/utils.rs +++ b/rsocket/src/utils.rs @@ -1,7 +1,9 @@ use super::spi::{Flux, RSocket}; use crate::error::RSocketError; use crate::payload::Payload; +use crate::runtime; use crate::Result; +use async_stream::stream; use async_trait::async_trait; use bytes::{Buf, BufMut, Bytes, BytesMut}; use futures::{pin_mut, FutureExt, Sink, SinkExt, Stream, StreamExt}; @@ -33,22 +35,20 @@ impl RSocket for EchoRSocket { fn request_stream(&self, req: Payload) -> Flux> { info!("{:?}", req); - // repeat 3 times. - Box::pin(futures::stream::iter(vec![ - Ok(req.clone()), - Ok(req.clone()), - Ok(req), - ])) + Box::pin(stream! { + yield Ok(req); + }) } fn request_channel(&self, mut reqs: Flux>) -> Flux> { let (sender, receiver) = mpsc::unbounded_channel(); - tokio::spawn(async move { + runtime::spawn(async move { while let Some(it) = reqs.next().await { info!("{:?}", it); sender.send(it).unwrap(); } }); + Box::pin(receiver) // or returns directly // reqs diff --git a/scripts/generate-certificate.sh b/scripts/generate-certificate.sh new file mode 100755 index 0000000..4c43490 --- /dev/null +++ b/scripts/generate-certificate.sh @@ -0,0 +1,59 @@ +# https://github.com/tokio-rs/tls/blob/master/tokio-native-tls/scripts/generate-certificate.sh + +#!/bin/bash +set -e + +cd $1 + +# prepare config file for root CA generation +cat <> root.cnf +[ req ] +distinguished_name = req_dn +[ req_dn ] +[ v3_ca ] +basicConstraints = CA:TRUE +keyUsage = digitalSignature, nonRepudiation, keyCertSign, cRLSign +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always +EOF + +ROOT_CA_KEY=root-ca.key.pem +ROOT_CA=root-ca.pem +ROOT_CA_DER=root-ca.der + +echo "Generate root CA key" +openssl genrsa -out $ROOT_CA_KEY 4096 + +echo "Generate root CA certificate" +openssl req -x509 -new -key $ROOT_CA_KEY -out $ROOT_CA -days 365 -SHA256 -subj "/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd" -config root.cnf -extensions v3_ca +openssl x509 -outform der -in $ROOT_CA -out $ROOT_CA_DER + +rm root.cnf + +# prepare config file for server certificate generation +cat <> server.cnf +extendedKeyUsage=serverAuth +subjectAltName = @alt_names +[alt_names] +DNS.1 = foobar.com +EOF + + +SERVER_KEY=server.key.pem +SERVER_CERT=cert.pem +SERVER_CERT_DER=cert.der +IDENTITY=identity.p12 +PASSPHRASE=mypass + +echo "Generate server key" +openssl genrsa -out $SERVER_KEY 4096 + +echo "Generate server certificate" +openssl req -out server.csr -key $SERVER_KEY -new -days 365 -SHA256 -subj "/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=foobar.com" +openssl x509 -req -days 365 -SHA256 -in server.csr -CA $ROOT_CA -CAkey $ROOT_CA_KEY -CAcreateserial -out $SERVER_CERT -extfile server.cnf +openssl x509 -outform der -in $SERVER_CERT -out $SERVER_CERT_DER + +openssl pkcs12 -export -out $IDENTITY -inkey $SERVER_KEY -in $SERVER_CERT -passout pass:$PASSPHRASE + +rm server.csr +rm server.cnf From 5cddb8c29e4b47b1c95d29c00811b91f671afffd Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Sun, 10 Jan 2021 22:33:20 +0800 Subject: [PATCH 40/70] feat: change transport api (#35) --- examples/Cargo.toml | 2 +- rsocket-test/tests/test_clients.rs | 3 - rsocket-transport-tcp/src/connection/tcp.rs | 50 ++------- rsocket-transport-tcp/src/connection/tls.rs | 46 +------- rsocket-transport-tcp/src/connection/uds.rs | 46 +------- rsocket-transport-wasm/Cargo.toml | 5 +- rsocket-transport-wasm/src/client.rs | 14 +-- rsocket-transport-wasm/src/connection.rs | 41 +------ rsocket-transport-websocket/src/connection.rs | 106 +++++++++--------- rsocket/src/core/client.rs | 50 +++++---- rsocket/src/core/mod.rs | 2 - rsocket/src/core/server.rs | 40 ++++--- rsocket/src/transport/socket.rs | 68 ++++++----- rsocket/src/transport/spi.rs | 50 +++------ 14 files changed, 185 insertions(+), 338 deletions(-) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 483cc67..4d48ada 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -48,4 +48,4 @@ path = "tls/server.rs" [[example]] name = "tls-client" -path = "tls/client.rs" \ No newline at end of file +path = "tls/client.rs" diff --git a/rsocket-test/tests/test_clients.rs b/rsocket-test/tests/test_clients.rs index f782398..50d99c6 100644 --- a/rsocket-test/tests/test_clients.rs +++ b/rsocket-test/tests/test_clients.rs @@ -74,7 +74,6 @@ fn test_websocket() { exec_request_response(&cli).await; exec_request_stream(&cli).await; exec_request_channel(&cli).await; - cli.close(); }); } @@ -120,7 +119,6 @@ fn test_tcp() { exec_request_response(&cli).await; exec_request_stream(&cli).await; exec_request_channel(&cli).await; - cli.close(); }); } @@ -176,7 +174,6 @@ fn test_unix() { exec_request_response(&cli).await; exec_request_stream(&cli).await; exec_request_channel(&cli).await; - cli.close(); }); } diff --git a/rsocket-transport-tcp/src/connection/tcp.rs b/rsocket-transport-tcp/src/connection/tcp.rs index 00252f3..6b0b4ce 100644 --- a/rsocket-transport-tcp/src/connection/tcp.rs +++ b/rsocket-transport-tcp/src/connection/tcp.rs @@ -1,57 +1,23 @@ -use super::codec::LengthBasedFrameCodec; -use futures::stream::{SplitSink, SplitStream}; use futures::{SinkExt, StreamExt}; -use rsocket_rust::async_trait; -use rsocket_rust::frame::Frame; -use rsocket_rust::transport::{Connection, Reader, Writer}; -use rsocket_rust::{error::RSocketError, Result}; use tokio::net::TcpStream; use tokio_util::codec::Framed; +use rsocket_rust::error::RSocketError; +use rsocket_rust::transport::{Connection, FrameSink, FrameStream}; + +use super::codec::LengthBasedFrameCodec; + #[derive(Debug)] pub struct TcpConnection { stream: TcpStream, } -struct InnerWriter { - sink: SplitSink, Frame>, -} - -struct InnerReader { - stream: SplitStream>, -} - -#[async_trait] -impl Writer for InnerWriter { - async fn write(&mut self, frame: Frame) -> Result<()> { - match self.sink.send(frame).await { - Ok(()) => Ok(()), - Err(e) => Err(RSocketError::IO(e).into()), - } - } -} - -#[async_trait] -impl Reader for InnerReader { - async fn read(&mut self) -> Option> { - self.stream - .next() - .await - .map(|next| next.map_err(|e| RSocketError::IO(e).into())) - } -} - impl Connection for TcpConnection { - fn split( - self, - ) -> ( - Box, - Box, - ) { + fn split(self) -> (Box, Box) { let (sink, stream) = Framed::new(self.stream, LengthBasedFrameCodec).split(); ( - Box::new(InnerWriter { sink }), - Box::new(InnerReader { stream }), + Box::new(sink.sink_map_err(|e| RSocketError::Other(e.into()))), + Box::new(stream.map(|next| next.map_err(|e| RSocketError::Other(e.into())))), ) } } diff --git a/rsocket-transport-tcp/src/connection/tls.rs b/rsocket-transport-tcp/src/connection/tls.rs index b2041c7..5d9f032 100644 --- a/rsocket-transport-tcp/src/connection/tls.rs +++ b/rsocket-transport-tcp/src/connection/tls.rs @@ -1,10 +1,7 @@ use super::codec::LengthBasedFrameCodec; -use futures::stream::{SplitSink, SplitStream}; use futures::{SinkExt, StreamExt}; -use rsocket_rust::async_trait; -use rsocket_rust::frame::Frame; -use rsocket_rust::transport::{Connection, Reader, Writer}; -use rsocket_rust::{error::RSocketError, Result}; +use rsocket_rust::error::RSocketError; +use rsocket_rust::transport::{Connection, FrameSink, FrameStream}; use tokio::net::TcpStream; use tokio_native_tls::TlsStream; use tokio_util::codec::Framed; @@ -14,45 +11,12 @@ pub struct TlsConnection { stream: TlsStream, } -struct InnerWriter { - sink: SplitSink, LengthBasedFrameCodec>, Frame>, -} - -struct InnerReader { - stream: SplitStream, LengthBasedFrameCodec>>, -} - -#[async_trait] -impl Writer for InnerWriter { - async fn write(&mut self, frame: Frame) -> Result<()> { - match self.sink.send(frame).await { - Ok(()) => Ok(()), - Err(e) => Err(RSocketError::IO(e).into()), - } - } -} - -#[async_trait] -impl Reader for InnerReader { - async fn read(&mut self) -> Option> { - self.stream - .next() - .await - .map(|next| next.map_err(|e| RSocketError::IO(e).into())) - } -} - impl Connection for TlsConnection { - fn split( - self, - ) -> ( - Box, - Box, - ) { + fn split(self) -> (Box, Box) { let (sink, stream) = Framed::new(self.stream, LengthBasedFrameCodec).split(); ( - Box::new(InnerWriter { sink }), - Box::new(InnerReader { stream }), + Box::new(sink.sink_map_err(|e| RSocketError::Other(e.into()))), + Box::new(stream.map(|it| it.map_err(|e| RSocketError::Other(e.into())))), ) } } diff --git a/rsocket-transport-tcp/src/connection/uds.rs b/rsocket-transport-tcp/src/connection/uds.rs index f62e831..8b454d3 100644 --- a/rsocket-transport-tcp/src/connection/uds.rs +++ b/rsocket-transport-tcp/src/connection/uds.rs @@ -1,10 +1,7 @@ use super::codec::LengthBasedFrameCodec; -use futures::stream::{SplitSink, SplitStream}; use futures::{SinkExt, StreamExt}; -use rsocket_rust::async_trait; -use rsocket_rust::frame::Frame; -use rsocket_rust::transport::{Connection, Reader, Writer}; -use rsocket_rust::{error::RSocketError, Result}; +use rsocket_rust::error::RSocketError; +use rsocket_rust::transport::{Connection, FrameSink, FrameStream}; use tokio::net::UnixStream; use tokio_util::codec::Framed; @@ -13,49 +10,16 @@ pub struct UnixConnection { stream: UnixStream, } -struct InnerWriter { - sink: SplitSink, Frame>, -} - -struct InnerReader { - stream: SplitStream>, -} - impl Connection for UnixConnection { - fn split( - self, - ) -> ( - Box, - Box, - ) { + fn split(self) -> (Box, Box) { let (sink, stream) = Framed::new(self.stream, LengthBasedFrameCodec).split(); ( - Box::new(InnerWriter { sink }), - Box::new(InnerReader { stream }), + Box::new(sink.sink_map_err(|e| RSocketError::Other(e.into()))), + Box::new(stream.map(|it| it.map_err(|e| RSocketError::Other(e.into())))), ) } } -#[async_trait] -impl Writer for InnerWriter { - async fn write(&mut self, frame: Frame) -> Result<()> { - match self.sink.send(frame).await { - Ok(()) => Ok(()), - Err(e) => Err(RSocketError::IO(e).into()), - } - } -} - -#[async_trait] -impl Reader for InnerReader { - async fn read(&mut self) -> Option> { - self.stream - .next() - .await - .map(|it| it.map_err(|e| RSocketError::IO(e).into())) - } -} - impl From for UnixConnection { fn from(stream: UnixStream) -> UnixConnection { UnixConnection { stream } diff --git a/rsocket-transport-wasm/Cargo.toml b/rsocket-transport-wasm/Cargo.toml index ad5fb1d..84d8274 100644 --- a/rsocket-transport-wasm/Cargo.toml +++ b/rsocket-transport-wasm/Cargo.toml @@ -12,12 +12,13 @@ description = "WASM Websocket RSocket transport implementation." [dependencies] bytes = "0.6.0" wasm-bindgen-futures = "0.4.19" -futures-channel = "0.3.8" -futures-util = "0.3.8" +futures-channel = "0.3.9" +futures-util = "0.3.9" js-sys = "0.3.46" serde = "1.0.118" serde_derive = "1.0.118" async-trait = "0.1.42" +log = "0.4.11" [dependencies.rsocket_rust] path = "../rsocket" diff --git a/rsocket-transport-wasm/src/client.rs b/rsocket-transport-wasm/src/client.rs index 45a6c06..62431d9 100644 --- a/rsocket-transport-wasm/src/client.rs +++ b/rsocket-transport-wasm/src/client.rs @@ -15,16 +15,6 @@ use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; use web_sys::{ErrorEvent, Event, FileReader, MessageEvent, ProgressEvent, WebSocket}; -macro_rules! console_log { - ($($t:tt)*) => (log(&format_args!($($t)*).to_string())) -} - -#[wasm_bindgen] -extern "C" { - #[wasm_bindgen(js_namespace = console)] - fn log(s: &str); -} - pub struct WebsocketClientTransport { url: String, } @@ -104,7 +94,7 @@ impl Transport for WebsocketClientTransport { // on error let on_error = Closure::wrap(Box::new(move |e: ErrorEvent| { - console_log!("websocket error: {}", e.message()); + log::error!("websocket error: {}", e.message()); }) as Box); ws.set_onerror(Some(on_error.as_ref().unchecked_ref())); @@ -112,7 +102,7 @@ impl Transport for WebsocketClientTransport { // on_close let on_close = Closure::once(Box::new(move |_e: Event| { - console_log!("websocket closed"); + log::info!("websocket closed"); }) as Box); ws.set_onclose(Some(on_close.as_ref().unchecked_ref())); on_close.forget(); diff --git a/rsocket-transport-wasm/src/connection.rs b/rsocket-transport-wasm/src/connection.rs index a93f921..bff9d11 100644 --- a/rsocket-transport-wasm/src/connection.rs +++ b/rsocket-transport-wasm/src/connection.rs @@ -1,8 +1,7 @@ -use async_trait::async_trait; use futures_channel::mpsc; use futures_util::{SinkExt, StreamExt}; -use rsocket_rust::transport::{Connection, Reader, Writer}; -use rsocket_rust::{error::RSocketError, frame::Frame, Result}; +use rsocket_rust::transport::{Connection, FrameSink, FrameStream}; +use rsocket_rust::{error::RSocketError, frame::Frame}; #[derive(Debug)] pub struct WebsocketConnection { @@ -10,47 +9,17 @@ pub struct WebsocketConnection { tx: mpsc::Sender, } -struct InnerWriter { - tx: mpsc::Sender, -} - -struct InnerReader { - rx: mpsc::Receiver, -} - impl WebsocketConnection { pub(crate) fn new(tx: mpsc::Sender, rx: mpsc::Receiver) -> WebsocketConnection { WebsocketConnection { rx, tx } } } -#[async_trait] -impl Writer for InnerWriter { - async fn write(&mut self, frame: Frame) -> Result<()> { - match self.tx.send(frame).await { - Ok(()) => Ok(()), - Err(e) => Err(RSocketError::Other(e.into()).into()), - } - } -} - -#[async_trait] -impl Reader for InnerReader { - async fn read(&mut self) -> Option> { - self.rx.next().await.map(|frame| Ok(frame)) - } -} - impl Connection for WebsocketConnection { - fn split( - self, - ) -> ( - Box, - Box, - ) { + fn split(self) -> (Box, Box) { ( - Box::new(InnerWriter { tx: self.tx }), - Box::new(InnerReader { rx: self.rx }), + Box::new(self.tx.sink_map_err(|e| RSocketError::Other(e.into()))), + Box::new(self.rx.map(|it| Ok(it))), ) } } diff --git a/rsocket-transport-websocket/src/connection.rs b/rsocket-transport-websocket/src/connection.rs index 52fbec9..eff31d2 100644 --- a/rsocket-transport-websocket/src/connection.rs +++ b/rsocket-transport-websocket/src/connection.rs @@ -1,79 +1,81 @@ use bytes::{BufMut, BytesMut}; -use futures::stream::{SplitSink, SplitStream}; -use futures::{SinkExt, StreamExt}; +use futures::stream::SplitSink; +use futures::{Sink, SinkExt, StreamExt}; use rsocket_rust::{ - async_trait, error::RSocketError, frame::Frame, - transport::{Connection, Reader, Writer}, + transport::{Connection, FrameSink, FrameStream}, utils::Writeable, - Result, }; +use std::result::Result; use tokio::net::TcpStream; -use tokio_tungstenite::{tungstenite::Message, WebSocketStream}; +use tokio_tungstenite::{ + tungstenite::{Error as WsError, Message}, + WebSocketStream, +}; #[derive(Debug)] pub struct WebsocketConnection { stream: WebSocketStream, } -struct InnerWriter { - sink: SplitSink, Message>, -} - -struct InnerReader { - stream: SplitStream>, -} - impl WebsocketConnection { pub(crate) fn new(stream: WebSocketStream) -> WebsocketConnection { WebsocketConnection { stream } } } -impl Connection for WebsocketConnection { - fn split( - self, - ) -> ( - Box, - Box, - ) { - let (sink, stream) = self.stream.split(); - ( - Box::new(InnerWriter { sink }), - Box::new(InnerReader { stream }), - ) +struct InnerSink(SplitSink, Message>); + +impl Sink for InnerSink { + type Error = WsError; + + fn poll_ready( + mut self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll> { + self.as_mut().0.poll_ready_unpin(cx) + } + + fn start_send(mut self: std::pin::Pin<&mut Self>, item: Frame) -> Result<(), Self::Error> { + let mut b = BytesMut::new(); + item.write_to(&mut b); + let msg = Message::binary(b.to_vec()); + self.as_mut().0.start_send_unpin(msg) + } + + fn poll_flush( + mut self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll> { + self.as_mut().0.poll_flush_unpin(cx) } -} -#[async_trait] -impl Writer for InnerWriter { - async fn write(&mut self, frame: Frame) -> Result<()> { - let mut bf = BytesMut::new(); - frame.write_to(&mut bf); - let msg = Message::binary(bf.to_vec()); - match self.sink.send(msg).await { - Ok(()) => Ok(()), - Err(e) => Err(RSocketError::Other(e.into()).into()), - } + fn poll_close( + mut self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll> { + self.as_mut().0.poll_close_unpin(cx) } } -#[async_trait] -impl Reader for InnerReader { - async fn read(&mut self) -> Option> { - match self.stream.next().await { - Some(Ok(msg)) => { - let raw = msg.into_data(); - let mut bf = BytesMut::new(); - bf.put_slice(&raw[..]); - match Frame::decode(&mut bf) { - Ok(frame) => Some(Ok(frame)), - Err(e) => Some(Err(e)), +impl Connection for WebsocketConnection { + fn split(self) -> (Box, Box) { + let (sink, stream) = self.stream.split(); + ( + Box::new(InnerSink(sink).sink_map_err(|e| RSocketError::Other(e.into()))), + Box::new(stream.map(|it| match it { + Ok(msg) => { + let raw = msg.into_data(); + let mut bf = BytesMut::new(); + bf.put_slice(&raw[..]); + match Frame::decode(&mut bf) { + Ok(frame) => Ok(frame), + Err(e) => Err(RSocketError::Other(e.into())), + } } - } - Some(Err(e)) => Some(Err(RSocketError::Other(e.into()).into())), - None => None, - } + Err(e) => Err(RSocketError::Other(e.into())), + })), + ) } } diff --git a/rsocket/src/core/client.rs b/rsocket/src/core/client.rs index da7c686..667d1e4 100644 --- a/rsocket/src/core/client.rs +++ b/rsocket/src/core/client.rs @@ -1,20 +1,22 @@ +use std::marker::PhantomData; +use std::net::SocketAddr; +use std::pin::Pin; +use std::sync::Arc; +use std::time::Duration; + +use async_trait::async_trait; +use futures::{future, FutureExt, Sink, SinkExt, Stream, StreamExt}; +use tokio::sync::{mpsc, Mutex, Notify}; + use crate::error::{RSocketError, ERR_CONN_CLOSED}; use crate::frame::{self, Frame}; use crate::payload::{Payload, SetupPayload, SetupPayloadBuilder}; use crate::runtime; use crate::spi::{ClientResponder, Flux, RSocket}; use crate::transport::{ - self, Acceptor, Connection, DuplexSocket, Reader, Splitter, Transport, Writer, + self, Acceptor, Connection, DuplexSocket, FrameSink, FrameStream, Splitter, Transport, }; use crate::Result; -use async_trait::async_trait; -use futures::{future, FutureExt, SinkExt, StreamExt}; -use std::marker::PhantomData; -use std::net::SocketAddr; -use std::pin::Pin; -use std::sync::Arc; -use std::time::Duration; -use tokio::sync::{mpsc, Mutex, Notify}; #[derive(Clone)] pub struct Client { @@ -120,7 +122,7 @@ where Some(Splitter::new(self.mtu)) }; - let (snd_tx, mut snd_rx) = mpsc::channel::(super::CHANNEL_SIZE); + let (snd_tx, mut snd_rx) = mpsc::unbounded_channel::(); let cloned_snd_tx = snd_tx.clone(); let mut socket = DuplexSocket::new(1, snd_tx, splitter).await; @@ -144,7 +146,7 @@ where break; } } - if let Err(e) = (&mut sink).write(frame).await { + if let Err(e) = sink.send(frame).await { error!("write frame failed: {}", e); break; } @@ -154,7 +156,7 @@ where // keepalive let keepalive_frame = frame::Keepalive::builder(0, Frame::FLAG_RESPOND).build(); - if let Err(e) = (&mut sink).write(keepalive_frame).await { + if let Err(e) = sink.send(keepalive_frame).await { error!("write frame failed: {}", e); break; } @@ -167,12 +169,15 @@ where let closer = self.closer.take(); let closed = Arc::new(Notify::new()); let closed_clone = closed.clone(); + + let (read_tx, mut read_rx) = mpsc::unbounded_channel::(); + runtime::spawn(async move { - while let Some(next) = stream.read().await { + while let Some(next) = stream.next().await { match next { Ok(frame) => { - if let Err(e) = cloned_socket.dispatch(frame, &acceptor).await { - error!("dispatch frame failed: {}", e); + if let Err(e) = read_tx.send(frame) { + error!("read next frame failed: {}", e); break; } } @@ -182,12 +187,21 @@ where } } } + }); + + runtime::spawn(async move { + while let Some(next) = read_rx.next().await { + if let Err(e) = cloned_socket.dispatch(next, &acceptor).await { + error!("dispatch frame failed: {}", e); + break; + } + } // workaround: send a notify frame that the connection has been closed. let close_frame = frame::Error::builder(0, 0) .set_code(ERR_CONN_CLOSED) .build(); - if let Err(_) = cloned_snd_tx.send(close_frame).await { + if let Err(_) = cloned_snd_tx.send(close_frame) { debug!("send close notify frame failed!"); } @@ -213,10 +227,6 @@ impl Client { pub async fn wait_for_close(self) { self.closed.notified().await } - - pub fn close(self) { - // TODO: support close - } } #[async_trait] diff --git a/rsocket/src/core/mod.rs b/rsocket/src/core/mod.rs index c778404..9730794 100644 --- a/rsocket/src/core/mod.rs +++ b/rsocket/src/core/mod.rs @@ -2,8 +2,6 @@ mod client; mod factory; mod server; -pub(crate) const CHANNEL_SIZE: usize = 32; - pub use client::{Client, ClientBuilder}; pub use factory::RSocketFactory; pub use server::ServerBuilder; diff --git a/rsocket/src/core/server.rs b/rsocket/src/core/server.rs index 999a9b3..9d48c8c 100644 --- a/rsocket/src/core/server.rs +++ b/rsocket/src/core/server.rs @@ -8,6 +8,7 @@ use crate::transport::{ }; use crate::utils::EmptyRSocket; use crate::Result; +use futures::{SinkExt, StreamExt}; use std::error::Error; use std::future::Future; use std::marker::PhantomData; @@ -111,34 +112,45 @@ where }; // Init duplex socket. - let (snd_tx, mut snd_rx) = mpsc::channel::(super::CHANNEL_SIZE); + let (snd_tx, mut snd_rx) = mpsc::unbounded_channel::(); let mut socket = DuplexSocket::new(0, snd_tx, splitter).await; // Begin loop for writing frames. runtime::spawn(async move { while let Some(frame) = snd_rx.recv().await { - if let Err(e) = writer.write(frame).await { + if let Err(e) = writer.send(frame).await { error!("write frame failed: {}", e); break; } } }); - loop { - match reader.read().await { - Some(Ok(frame)) => { - if let Err(e) = socket.dispatch(frame, &acceptor).await { - error!("dispatch incoming frame failed: {}", e); + let (read_tx, mut read_rx) = mpsc::unbounded_channel::(); + + runtime::spawn(async move { + loop { + match reader.next().await { + Some(Ok(frame)) => { + if let Err(e) = read_tx.send(frame) { + error!("read next frame failed: {}", e); + break; + } + } + Some(Err(e)) => { + error!("read next frame failed: {}", e); + break; + } + None => { break; } } - Some(Err(e)) => { - error!("read next frame failed: {}", e); - break; - } - None => { - break; - } + } + }); + + while let Some(frame) = read_rx.next().await { + if let Err(e) = socket.dispatch(frame, &acceptor).await { + error!("dispatch incoming frame failed: {}", e); + break; } } diff --git a/rsocket/src/transport/socket.rs b/rsocket/src/transport/socket.rs index 007a37b..b3e3b6b 100644 --- a/rsocket/src/transport/socket.rs +++ b/rsocket/src/transport/socket.rs @@ -22,7 +22,7 @@ use tokio::sync::{mpsc, oneshot, RwLock}; pub(crate) struct DuplexSocket { seq: StreamID, responder: Responder, - tx: mpsc::Sender, + tx: mpsc::UnboundedSender, handlers: Arc>, canceller: mpsc::Sender, splitter: Option, @@ -45,7 +45,7 @@ enum Handler { impl DuplexSocket { pub(crate) async fn new( first_stream_id: u32, - tx: mpsc::Sender, + tx: mpsc::UnboundedSender, splitter: Option, ) -> DuplexSocket { let (canceller_tx, canceller_rx) = mpsc::channel::(32); @@ -85,7 +85,7 @@ impl DuplexSocket { if let Some(b) = m { bu = bu.set_metadata(b); } - self.tx.send(bu.build()).await.expect("Send setup failed"); + self.tx.send(bu.build()).expect("Send setup failed"); } #[inline] @@ -127,7 +127,7 @@ impl DuplexSocket { .set_code(error::ERR_REJECT_SETUP) .set_data(Bytes::from(errmsg)) .build(); - self.tx.send(sending).await.expect("Reject setup failed"); + self.tx.send(sending).expect("Reject setup failed"); return; } } @@ -416,7 +416,7 @@ impl DuplexSocket { .set_code(error::ERR_APPLICATION) .set_data(Bytes::from("TODO: should be error details")) .build(); - if let Err(e) = tx.send(sending).await { + if let Err(e) = tx.send(sending) { error!("respond REQUEST_RESPONSE failed: {}", e); } } @@ -442,13 +442,12 @@ impl DuplexSocket { .set_code(error::ERR_APPLICATION) .set_data(Bytes::from(format!("{}", e))) .build(); - tx.send(sending).await.expect("Send stream response failed"); + tx.send(sending).expect("Send stream response failed"); } }; } let complete = frame::Payload::builder(sid, Frame::FLAG_COMPLETE).build(); tx.send(complete) - .await .expect("Send stream complete response failed"); }); } @@ -466,7 +465,7 @@ impl DuplexSocket { // TODO: support custom RequestN. let request_n = frame::RequestN::builder(sid, 0).build(); - if let Err(e) = tx.send(request_n).await { + if let Err(e) = tx.send(request_n) { error!("respond REQUEST_N failed: {}", e); } @@ -488,10 +487,10 @@ impl DuplexSocket { .set_data(Bytes::from(format!("{}", e))) .build(), }; - tx.send(sending).await.expect("Send failed!"); + tx.send(sending).expect("Send failed!"); } let complete = frame::Payload::builder(sid, Frame::FLAG_COMPLETE).build(); - if let Err(e) = tx.send(complete).await { + if let Err(e) = tx.send(complete) { error!("complete REQUEST_CHANNEL failed: {}", e); } }); @@ -511,7 +510,7 @@ impl DuplexSocket { if let Some(b) = data { sending = sending.set_data(b); } - if let Err(e) = self.tx.send(sending.build()).await { + if let Err(e) = self.tx.send(sending.build()) { error!("respond KEEPALIVE failed: {}", e); } } @@ -519,7 +518,7 @@ impl DuplexSocket { #[inline] async fn try_send_channel( splitter: &Option, - tx: &mut mpsc::Sender, + tx: &mut mpsc::UnboundedSender, sid: u32, res: Payload, flag: u16, @@ -541,7 +540,7 @@ impl DuplexSocket { .build() }; // send frame - if let Err(e) = tx.send(sending).await { + if let Err(e) = tx.send(sending) { error!("send request_channel failed: {}", e); return; } @@ -562,7 +561,7 @@ impl DuplexSocket { .build() }; // send frame - if let Err(e) = tx.send(sending).await { + if let Err(e) = tx.send(sending) { error!("send request_channel failed: {}", e); } } @@ -570,7 +569,7 @@ impl DuplexSocket { let sending = frame::RequestChannel::builder(sid, flag) .set_all(res.split()) .build(); - if let Err(e) = tx.send(sending).await { + if let Err(e) = tx.send(sending) { error!("send request_channel failed: {}", e); } } @@ -578,9 +577,9 @@ impl DuplexSocket { } #[inline] - async fn try_send_complete(tx: &mut mpsc::Sender, sid: u32, flag: u16) { + async fn try_send_complete(tx: &mut mpsc::UnboundedSender, sid: u32, flag: u16) { let sending = frame::Payload::builder(sid, flag).build(); - if let Err(e) = tx.send(sending).await { + if let Err(e) = tx.send(sending) { error!("respond failed: {}", e); } } @@ -588,7 +587,7 @@ impl DuplexSocket { #[inline] async fn try_send_payload( splitter: &Option, - tx: &mut mpsc::Sender, + tx: &mut mpsc::UnboundedSender, sid: u32, res: Payload, flag: u16, @@ -609,7 +608,7 @@ impl DuplexSocket { .build() }; // send frame - if let Err(e) = tx.send(sending).await { + if let Err(e) = tx.send(sending) { error!("send payload failed: {}", e); return; } @@ -626,7 +625,7 @@ impl DuplexSocket { .build() }; // send frame - if let Err(e) = tx.send(sending).await { + if let Err(e) = tx.send(sending) { error!("send payload failed: {}", e); } } @@ -634,7 +633,7 @@ impl DuplexSocket { let sending = frame::Payload::builder(sid, flag) .set_all(res.split()) .build(); - if let Err(e) = tx.send(sending).await { + if let Err(e) = tx.send(sending) { error!("respond failed: {}", e); } } @@ -652,11 +651,8 @@ impl RSocket for DuplexSocket { if let Some(b) = m { bu = bu.set_metadata(b); } - tx.send(bu.build()).await?; + tx.send(bu.build())?; Ok(()) - // if let Err(e) = tx.send(bu.build()).await { - // error!("send metadata_push failed: {}", e); - // } } async fn fire_and_forget(&self, req: Payload) -> Result<()> { @@ -682,7 +678,7 @@ impl RSocket for DuplexSocket { .build() }; // send frame - tx.send(sending).await?; + tx.send(sending)?; } prev = Some(next); cuts += 1; @@ -700,13 +696,13 @@ impl RSocket for DuplexSocket { .build() }; // send frame - tx.send(sending).await?; + tx.send(sending)?; } None => { let sending = frame::RequestFNF::builder(sid, 0) .set_all(req.split()) .build(); - tx.send(sending).await?; + tx.send(sending)?; } } Ok(()) @@ -741,7 +737,7 @@ impl RSocket for DuplexSocket { .build() }; // send frame - if let Err(e) = sender.send(sending).await { + if let Err(e) = sender.send(sending) { error!("send request_response failed: {}", e); return; } @@ -762,7 +758,7 @@ impl RSocket for DuplexSocket { .build() }; // send frame - if let Err(e) = sender.send(sending).await { + if let Err(e) = sender.send(sending) { error!("send request_response failed: {}", e); } } @@ -772,7 +768,7 @@ impl RSocket for DuplexSocket { .set_all(req.split()) .build(); // send frame - if let Err(e) = sender.send(sending).await { + if let Err(e) = sender.send(sending) { error!("send request_response failed: {}", e); } } @@ -812,7 +808,7 @@ impl RSocket for DuplexSocket { .build() }; // send frame - if let Err(e) = tx.send(sending).await { + if let Err(e) = tx.send(sending) { error!("send request_stream failed: {}", e); return; } @@ -833,7 +829,7 @@ impl RSocket for DuplexSocket { .build() }; // send frame - if let Err(e) = tx.send(sending).await { + if let Err(e) = tx.send(sending) { error!("send request_stream failed: {}", e); } } @@ -841,7 +837,7 @@ impl RSocket for DuplexSocket { let sending = frame::RequestStream::builder(sid, 0) .set_all(input.split()) .build(); - if let Err(e) = tx.send(sending).await { + if let Err(e) = tx.send(sending) { error!("send request_stream failed: {}", e); } } @@ -877,14 +873,14 @@ impl RSocket for DuplexSocket { .set_code(error::ERR_APPLICATION) .set_data(Bytes::from(format!("{}", e))) .build(); - if let Err(e) = tx.send(sending).await { + if let Err(e) = tx.send(sending) { error!("send REQUEST_CHANNEL failed: {}", e); } } }; } let sending = frame::Payload::builder(sid, Frame::FLAG_COMPLETE).build(); - if let Err(e) = tx.send(sending).await { + if let Err(e) = tx.send(sending) { error!("complete REQUEST_CHANNEL failed: {}", e); } }); diff --git a/rsocket/src/transport/spi.rs b/rsocket/src/transport/spi.rs index 6778277..dfd5b01 100644 --- a/rsocket/src/transport/spi.rs +++ b/rsocket/src/transport/spi.rs @@ -1,40 +1,31 @@ -use crate::frame::Frame; -use crate::payload::SetupPayload; -use crate::spi::{ClientResponder, RSocket, ServerResponder}; -use crate::{Error, Result}; -use async_trait::async_trait; -use futures::channel::{mpsc, oneshot}; -use futures::sink::Sink; -use futures::stream::Stream; use std::future::Future; +use std::io::Error as IOError; use std::marker::Unpin; use std::pin::Pin; +use std::result::Result as StdResult; use std::sync::Arc; + +use async_trait::async_trait; +use futures::channel::{mpsc, oneshot}; +use futures::{Sink, Stream}; use tokio::sync::Notify; +use crate::payload::SetupPayload; +use crate::spi::{ClientResponder, RSocket, ServerResponder}; +use crate::{error::RSocketError, frame::Frame}; +use crate::{Error, Result}; + #[derive(Clone)] pub(crate) enum Acceptor { Simple(Arc), Generate(Arc), } -#[async_trait] -pub trait Reader { - async fn read(&mut self) -> Option>; -} - -#[async_trait] -pub trait Writer { - async fn write(&mut self, frame: Frame) -> Result<()>; -} +pub type FrameSink = dyn Sink + Send + Unpin; +pub type FrameStream = dyn Stream> + Send + Unpin; pub trait Connection { - fn split( - self, - ) -> ( - Box, - Box, - ); + fn split(self) -> (Box, Box); } #[async_trait] @@ -44,19 +35,6 @@ pub trait Transport { async fn connect(self) -> Result; } -#[async_trait] -pub trait ServerTransportOld { - type Item; - - async fn start( - self, - starter: Option>, - acceptor: Box Result<()> + Send + Sync>, - ) -> Result<()> - where - Self::Item: Transport + Sized; -} - #[async_trait] pub trait ServerTransport { type Item: Transport; From 69504597322fe80589f70f73758ff779e77a5922 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Mon, 11 Jan 2021 22:51:36 +0800 Subject: [PATCH 41/70] fix: register client-side responder correctly (#36) --- rsocket/src/core/client.rs | 10 +++++++--- rsocket/src/core/server.rs | 11 +++++------ rsocket/src/lib.rs | 2 ++ rsocket/src/transport/socket.rs | 20 ++++++++++---------- rsocket/src/transport/spi.rs | 6 ------ rsocket/src/utils.rs | 14 +++++++++----- 6 files changed, 33 insertions(+), 30 deletions(-) diff --git a/rsocket/src/core/client.rs b/rsocket/src/core/client.rs index 667d1e4..2368642 100644 --- a/rsocket/src/core/client.rs +++ b/rsocket/src/core/client.rs @@ -14,7 +14,7 @@ use crate::payload::{Payload, SetupPayload, SetupPayloadBuilder}; use crate::runtime; use crate::spi::{ClientResponder, Flux, RSocket}; use crate::transport::{ - self, Acceptor, Connection, DuplexSocket, FrameSink, FrameStream, Splitter, Transport, + self, Connection, DuplexSocket, FrameSink, FrameStream, Splitter, Transport, }; use crate::Result; @@ -127,7 +127,11 @@ where let mut socket = DuplexSocket::new(1, snd_tx, splitter).await; let mut cloned_socket = socket.clone(); - let acceptor: Option = self.responder.map(|it| Acceptor::Simple(Arc::new(it))); + + if let Some(f) = self.responder { + let responder = f(); + socket.bind_responder(responder).await; + } let conn = tp.connect().await?; let (mut sink, mut stream) = conn.split(); @@ -191,7 +195,7 @@ where runtime::spawn(async move { while let Some(next) = read_rx.next().await { - if let Err(e) = cloned_socket.dispatch(next, &acceptor).await { + if let Err(e) = cloned_socket.dispatch(next, None).await { error!("dispatch frame failed: {}", e); break; } diff --git a/rsocket/src/core/server.rs b/rsocket/src/core/server.rs index 9d48c8c..60da6d3 100644 --- a/rsocket/src/core/server.rs +++ b/rsocket/src/core/server.rs @@ -3,9 +3,7 @@ use crate::frame::{self, Frame}; use crate::payload::SetupPayload; use crate::runtime; use crate::spi::{RSocket, ServerResponder}; -use crate::transport::{ - Acceptor, Connection, DuplexSocket, ServerTransport, Splitter, Transport, MIN_MTU, -}; +use crate::transport::{Connection, DuplexSocket, ServerTransport, Splitter, Transport, MIN_MTU}; use crate::utils::EmptyRSocket; use crate::Result; use futures::{SinkExt, StreamExt}; @@ -70,7 +68,7 @@ where { pub async fn serve(mut self) -> Result<()> { let mut server_transport = self.transport.take().expect("missing transport"); - let acceptor = self.on_setup.map(|v| Acceptor::Generate(Arc::new(v))); + // let acceptor = self.on_setup.map(|v| Acceptor::Generate(Arc::new(v))); let mtu = self.mtu; @@ -80,6 +78,7 @@ where invoke(); } + let acceptor = Arc::new(self.on_setup); while let Some(next) = server_transport.next().await { match next { Ok(tp) => { @@ -99,7 +98,7 @@ where } #[inline] - async fn on_transport(mtu: usize, tp: C, acceptor: Option) -> Result<()> { + async fn on_transport(mtu: usize, tp: C, acceptor: Arc>) -> Result<()> { // Establish connection. let conn = tp.connect().await?; let (mut writer, mut reader) = conn.split(); @@ -148,7 +147,7 @@ where }); while let Some(frame) = read_rx.next().await { - if let Err(e) = socket.dispatch(frame, &acceptor).await { + if let Err(e) = socket.dispatch(frame, acceptor.as_ref().as_ref()).await { error!("dispatch incoming frame failed: {}", e); break; } diff --git a/rsocket/src/lib.rs b/rsocket/src/lib.rs index a1703b7..073d267 100644 --- a/rsocket/src/lib.rs +++ b/rsocket/src/lib.rs @@ -96,6 +96,8 @@ pub use async_stream::stream; /// A re-export of [`async-trait`](https://docs.rs/async-trait) for use with RSocket trait implementation. pub use async_trait::async_trait; +#[macro_use] +extern crate anyhow; #[macro_use] extern crate log; #[macro_use] diff --git a/rsocket/src/transport/socket.rs b/rsocket/src/transport/socket.rs index b3e3b6b..261f88e 100644 --- a/rsocket/src/transport/socket.rs +++ b/rsocket/src/transport/socket.rs @@ -4,7 +4,7 @@ use super::spi::*; use crate::error::{self, RSocketError}; use crate::frame::{self, Body, Frame}; use crate::payload::{Payload, SetupPayload}; -use crate::spi::{Flux, RSocket}; +use crate::spi::{Flux, RSocket, ServerResponder}; use crate::utils::EmptyRSocket; use crate::{runtime, Result}; use async_stream::stream; @@ -103,7 +103,7 @@ impl DuplexSocket { pub(crate) async fn dispatch( &mut self, frame: Frame, - acceptor: &Option, + acceptor: Option<&ServerResponder>, ) -> Result<()> { if let Some(frame) = self.join_frame(frame).await { self.process_once(frame, acceptor).await; @@ -112,7 +112,7 @@ impl DuplexSocket { } #[inline] - async fn process_once(&mut self, msg: Frame, acceptor: &Option) { + async fn process_once(&mut self, msg: Frame, acceptor: Option<&ServerResponder>) { let sid = msg.get_stream_id(); let flag = msg.get_flag(); debug_frame(false, &msg); @@ -343,10 +343,14 @@ impl DuplexSocket { } } + pub(crate) async fn bind_responder(&self, responder: Box) { + self.responder.set(responder).await; + } + #[inline] async fn on_setup( &self, - acceptor: &Option, + acceptor: Option<&ServerResponder>, sid: u32, flag: u16, setup: SetupPayload, @@ -356,11 +360,7 @@ impl DuplexSocket { self.responder.set(Box::new(EmptyRSocket)).await; Ok(()) } - Some(Acceptor::Simple(gen)) => { - self.responder.set(gen()).await; - Ok(()) - } - Some(Acceptor::Generate(gen)) => match gen(setup, Box::new(self.clone())) { + Some(gen) => match gen(setup, Box::new(self.clone())) { Ok(it) => { self.responder.set(it).await; Ok(()) @@ -414,7 +414,7 @@ impl DuplexSocket { Err(e) => { let sending = frame::Error::builder(sid, 0) .set_code(error::ERR_APPLICATION) - .set_data(Bytes::from("TODO: should be error details")) + .set_data(Bytes::from(e.to_string())) .build(); if let Err(e) = tx.send(sending) { error!("respond REQUEST_RESPONSE failed: {}", e); diff --git a/rsocket/src/transport/spi.rs b/rsocket/src/transport/spi.rs index dfd5b01..1198c6c 100644 --- a/rsocket/src/transport/spi.rs +++ b/rsocket/src/transport/spi.rs @@ -15,12 +15,6 @@ use crate::spi::{ClientResponder, RSocket, ServerResponder}; use crate::{error::RSocketError, frame::Frame}; use crate::{Error, Result}; -#[derive(Clone)] -pub(crate) enum Acceptor { - Simple(Arc), - Generate(Arc), -} - pub type FrameSink = dyn Sink + Send + Unpin; pub type FrameStream = dyn Stream> + Send + Unpin; diff --git a/rsocket/src/utils.rs b/rsocket/src/utils.rs index 1bff3bf..c54c58e 100644 --- a/rsocket/src/utils.rs +++ b/rsocket/src/utils.rs @@ -60,23 +60,27 @@ pub(crate) struct EmptyRSocket; #[async_trait] impl RSocket for EmptyRSocket { async fn metadata_push(&self, _req: Payload) -> Result<()> { - Err(RSocketError::ApplicationException("UNIMPLEMENT".into()).into()) + Err(anyhow!("UNIMPLEMENT")) } async fn fire_and_forget(&self, _req: Payload) -> Result<()> { - Err(RSocketError::ApplicationException("UNIMPLEMENT".into()).into()) + Err(anyhow!("UNIMPLEMENT")) } async fn request_response(&self, _req: Payload) -> Result> { - Err(RSocketError::ApplicationException("UNIMPLEMENT".into()).into()) + Err(anyhow!("UNIMPLEMENT")) } fn request_stream(&self, _req: Payload) -> Flux> { - Box::pin(futures::stream::empty()) + Box::pin(stream! { + yield Err(anyhow!("UNIMPLEMENT")); + }) } fn request_channel(&self, _reqs: Flux>) -> Flux> { - Box::pin(futures::stream::empty()) + Box::pin(stream! { + yield Err(anyhow!("UNIMPLEMENT")); + }) } } From e31d71c5775d92babc27efc0d984d989b0780147 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Tue, 12 Jan 2021 10:35:56 +0800 Subject: [PATCH 42/70] feat: migrate to tokio v1 --- examples/Cargo.toml | 6 +++--- rsocket-messaging/Cargo.toml | 8 ++++---- rsocket-test/Cargo.toml | 12 ++++++------ rsocket-transport-tcp/Cargo.toml | 14 ++++++------- rsocket-transport-wasm/Cargo.toml | 8 ++++---- rsocket-transport-websocket/Cargo.toml | 12 ++++++------ rsocket/Cargo.toml | 12 ++++++------ rsocket/src/core/client.rs | 4 ++-- rsocket/src/core/server.rs | 2 +- rsocket/src/transport/socket.rs | 27 ++++++++++++++++++-------- rsocket/src/utils.rs | 9 ++++++--- 11 files changed, 64 insertions(+), 50 deletions(-) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 4d48ada..ca4377e 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -6,9 +6,9 @@ edition = "2018" publish = false [dev-dependencies] -log = "0.4.11" +log = "0.4.13" env_logger = "0.8.2" -futures = "0.3.8" +futures = "0.3.9" clap = "2.33.3" [dev-dependencies.rsocket_rust] @@ -22,7 +22,7 @@ features = ["tls"] path = "../rsocket-transport-websocket" [dev-dependencies.tokio] -version = "0.3.6" +version = "1.0.1" default-features = false features = ["full"] diff --git a/rsocket-messaging/Cargo.toml b/rsocket-messaging/Cargo.toml index 36a3a4b..ed6cabd 100644 --- a/rsocket-messaging/Cargo.toml +++ b/rsocket-messaging/Cargo.toml @@ -10,10 +10,10 @@ homepage = "https://github.com/rsocket/rsocket-rust" description = "Communicate with Spring RSocket Messaging." [dependencies] -futures = "0.3.8" -bytes = "0.6.0" -serde = "1.0.118" -serde_json = "1.0.60" +futures = "0.3.9" +bytes = "1.0.1" +serde = "1.0.119" +serde_json = "1.0.61" serde_cbor = "0.11.1" hex = "0.4.2" url = "2.2.0" diff --git a/rsocket-test/Cargo.toml b/rsocket-test/Cargo.toml index a00a015..0da251b 100644 --- a/rsocket-test/Cargo.toml +++ b/rsocket-test/Cargo.toml @@ -7,13 +7,13 @@ publish = false [dev-dependencies] log = "0.4" -futures = "0.3.8" +futures = "0.3.9" env_logger = "0.8.2" -bytes = "0.6.0" +bytes = "1.0.1" hex = "0.4.2" -rand = "0.8.0" -serde = "1.0.118" -serde_derive = "1.0.118" +rand = "0.8.1" +serde = "1.0.119" +serde_derive = "1.0.119" [dev-dependencies.rsocket_rust] path = "../rsocket" @@ -29,6 +29,6 @@ path = "../rsocket-transport-websocket" path = "../rsocket-messaging" [dev-dependencies.tokio] -version = "0.3.6" +version = "1.0.1" default-features = false features = ["full"] diff --git a/rsocket-transport-tcp/Cargo.toml b/rsocket-transport-tcp/Cargo.toml index 589fe31..d85b109 100644 --- a/rsocket-transport-tcp/Cargo.toml +++ b/rsocket-transport-tcp/Cargo.toml @@ -14,24 +14,24 @@ default = [] tls = ["tokio-native-tls"] [dependencies] -log = "0.4.11" -futures = "0.3.8" -bytes = "0.6.0" +log = "0.4.13" +futures = "0.3.9" +bytes = "1.0.1" [dependencies.rsocket_rust] path = "../rsocket" features = ["frame"] [dependencies.tokio] -version = "0.3.6" +version = "1.0.1" default-features = false -features = [ "rt", "rt-multi-thread", "net", "sync", "stream", "io-util", "macros" ] +features = [ "rt", "rt-multi-thread", "net", "sync", "io-util", "macros" ] [dependencies.tokio-util] -version = "0.5.1" +version = "0.6.0" default-features = false features = ["codec"] [dependencies.tokio-native-tls] optional = true -version = "0.2.0" +version = "0.3.0" diff --git a/rsocket-transport-wasm/Cargo.toml b/rsocket-transport-wasm/Cargo.toml index 84d8274..59d6f3b 100644 --- a/rsocket-transport-wasm/Cargo.toml +++ b/rsocket-transport-wasm/Cargo.toml @@ -10,15 +10,15 @@ homepage = "https://github.com/rsocket/rsocket-rust" description = "WASM Websocket RSocket transport implementation." [dependencies] -bytes = "0.6.0" +bytes = "1.0.1" wasm-bindgen-futures = "0.4.19" futures-channel = "0.3.9" futures-util = "0.3.9" js-sys = "0.3.46" -serde = "1.0.118" -serde_derive = "1.0.118" +serde = "1.0.119" +serde_derive = "1.0.119" async-trait = "0.1.42" -log = "0.4.11" +log = "0.4.13" [dependencies.rsocket_rust] path = "../rsocket" diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index ca35208..2df740d 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -10,17 +10,17 @@ homepage = "https://github.com/rsocket/rsocket-rust" description = "Websocket RSocket transport implementation." [dependencies] -log = "0.4.11" -futures = "0.3.8" -bytes = "0.6.0" +log = "0.4.13" +futures = "0.3.9" +bytes = "1.0.1" url = "2.2.0" -tokio-tungstenite = "0.12.0" +tokio-tungstenite = "0.13.0" [dependencies.rsocket_rust] path = "../rsocket" features = ["frame"] [dependencies.tokio] -version = "0.3.6" +version = "1.0.1" default-features = false -features = [ "rt", "rt-multi-thread", "net", "sync", "stream" ] +features = [ "rt", "rt-multi-thread", "net", "sync"] diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index 965f2fc..775f7d1 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -10,23 +10,23 @@ homepage = "https://github.com/rsocket/rsocket-rust" description = "rsocket-rust is an implementation of the RSocket protocol in Rust." [dependencies] -log = "0.4.11" -bytes = "0.6.0" -futures = "0.3.8" +log = "0.4.13" +bytes = "1.0.1" +futures = "0.3.9" lazy_static = "1.4.0" async-trait = "0.1.42" dashmap = "4.0.1" thiserror = "1.0.23" -anyhow = "1.0.36" +anyhow = "1.0.38" async-stream = "0.3.0" [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen-futures = "0.4.19" [dependencies.tokio] -version = "0.3.6" +version = "1.0.1" default-features = false -features = [ "rt", "rt-multi-thread", "sync", "stream", "time" ] +features = [ "rt", "rt-multi-thread", "sync", "time" ] [features] default = [] diff --git a/rsocket/src/core/client.rs b/rsocket/src/core/client.rs index 2368642..810502a 100644 --- a/rsocket/src/core/client.rs +++ b/rsocket/src/core/client.rs @@ -143,7 +143,7 @@ where runtime::spawn(async move { loop { // send keepalive if timeout - match tokio::time::timeout(tick_period, snd_rx.next()).await { + match tokio::time::timeout(tick_period, snd_rx.recv()).await { Ok(Some(frame)) => { if let frame::Body::Error(e) = frame.get_body_ref() { if e.get_code() == ERR_CONN_CLOSED { @@ -194,7 +194,7 @@ where }); runtime::spawn(async move { - while let Some(next) = read_rx.next().await { + while let Some(next) = read_rx.recv().await { if let Err(e) = cloned_socket.dispatch(next, None).await { error!("dispatch frame failed: {}", e); break; diff --git a/rsocket/src/core/server.rs b/rsocket/src/core/server.rs index 60da6d3..c81642e 100644 --- a/rsocket/src/core/server.rs +++ b/rsocket/src/core/server.rs @@ -146,7 +146,7 @@ where } }); - while let Some(frame) = read_rx.next().await { + while let Some(frame) = read_rx.recv().await { if let Err(e) = socket.dispatch(frame, acceptor.as_ref().as_ref()).await { error!("dispatch incoming frame failed: {}", e); break; diff --git a/rsocket/src/transport/socket.rs b/rsocket/src/transport/socket.rs index 261f88e..6f1d99b 100644 --- a/rsocket/src/transport/socket.rs +++ b/rsocket/src/transport/socket.rs @@ -15,7 +15,6 @@ use futures::{Sink, SinkExt, Stream, StreamExt}; use std::future::Future; use std::pin::Pin; use std::sync::Arc; -use tokio::prelude::*; use tokio::sync::{mpsc, oneshot, RwLock}; #[derive(Clone)] @@ -95,7 +94,7 @@ impl DuplexSocket { #[inline] async fn loop_canceller(&self, mut rx: mpsc::Receiver) { - while let Some(sid) = rx.next().await { + while let Some(sid) = rx.recv().await { self.handlers.remove(&sid); } } @@ -456,12 +455,16 @@ impl DuplexSocket { async fn on_request_channel(&self, sid: u32, flag: u16, first: Payload) { let responder = self.responder.clone(); let tx = self.tx.clone(); - let (sender, receiver) = mpsc::channel::>(32); + let (sender, mut receiver) = mpsc::channel::>(32); sender.send(Ok(first)).await.expect("Send failed!"); self.register_handler(sid, Handler::ReqRC(sender)).await; runtime::spawn(async move { // respond client channel - let mut outputs = responder.request_channel(Box::pin(receiver)); + let mut outputs = responder.request_channel(Box::pin(stream! { + while let Some(it) = receiver.recv().await{ + yield it; + } + })); // TODO: support custom RequestN. let request_n = frame::RequestN::builder(sid, 0).build(); @@ -784,7 +787,7 @@ impl RSocket for DuplexSocket { let sid = self.seq.next(); let tx = self.tx.clone(); // register handler - let (sender, receiver) = mpsc::channel::>(32); + let (sender, mut receiver) = mpsc::channel::>(32); let handlers = self.handlers.clone(); let splitter = self.splitter.clone(); runtime::spawn(async move { @@ -843,14 +846,18 @@ impl RSocket for DuplexSocket { } } }); - Box::pin(receiver) + Box::pin(stream! { + while let Some(it) = receiver.recv().await{ + yield it; + } + }) } fn request_channel(&self, mut reqs: Flux>) -> Flux> { let sid = self.seq.next(); let mut tx = self.tx.clone(); // register handler - let (sender, receiver) = mpsc::channel::>(32); + let (sender, mut receiver) = mpsc::channel::>(32); let handlers = self.handlers.clone(); let splitter = self.splitter.clone(); runtime::spawn(async move { @@ -884,7 +891,11 @@ impl RSocket for DuplexSocket { error!("complete REQUEST_CHANNEL failed: {}", e); } }); - Box::pin(receiver) + Box::pin(stream! { + while let Some(it) = receiver.recv().await{ + yield it; + } + }) } } diff --git a/rsocket/src/utils.rs b/rsocket/src/utils.rs index c54c58e..b5d4b64 100644 --- a/rsocket/src/utils.rs +++ b/rsocket/src/utils.rs @@ -41,15 +41,18 @@ impl RSocket for EchoRSocket { } fn request_channel(&self, mut reqs: Flux>) -> Flux> { - let (sender, receiver) = mpsc::unbounded_channel(); + let (sender, mut receiver) = mpsc::unbounded_channel(); runtime::spawn(async move { while let Some(it) = reqs.next().await { info!("{:?}", it); sender.send(it).unwrap(); } }); - - Box::pin(receiver) + Box::pin(stream! { + while let Some(it) = receiver.recv().await { + yield it; + } + }) // or returns directly // reqs } From bb86d48da372996ab4cd776c4dbb294a5e9487c9 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Tue, 12 Jan 2021 11:12:37 +0800 Subject: [PATCH 43/70] chore: add RSocket trait example in readme --- README.md | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 73 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 79401e1..886afcf 100644 --- a/README.md +++ b/README.md @@ -21,12 +21,12 @@ Add dependencies in your `Cargo.toml`. ```toml [dependencies] -tokio = "0.3.6" -rsocket_rust = "0.7.0" +tokio = "1.0" +rsocket_rust = "0.7" # add transport dependencies: -# rsocket_rust_transport_tcp = "0.7.0" -# rsocket_rust_transport_websocket = "0.7.0" +# rsocket_rust_transport_tcp = "0.7" +# rsocket_rust_transport_websocket = "0.7" ``` ### Server @@ -74,7 +74,75 @@ async fn main() -> Result<()> { .build(); let res = cli.request_response(req).await?; println!("got: {:?}", res); - cli.close(); + + // If you want to block until socket disconnected. + cli.wait_for_close().await; + + Ok(()) +} + +``` + +### Implement RSocket trait + +Example for access Redis([crates](https://crates.io/crates/redis)): + +> NOTICE: add dependency in Cargo.toml => redis = { version = "0.19.0", features = [ "aio" ] } + +```rust +use redis::Client as RedisClient; +use rsocket_rust::async_trait; +use rsocket_rust::prelude::*; +use rsocket_rust::Result; +use std::str::FromStr; + +#[derive(Clone)] +pub struct RedisDao { + inner: RedisClient, +} + +// Create RedisDao from str. +// Example: RedisDao::from_str("redis://127.0.0.1").expect("Connect redis failed!"); +impl FromStr for RedisDao { + type Err = redis::RedisError; + + fn from_str(s: &str) -> std::result::Result { + let client = redis::Client::open(s)?; + Ok(RedisDao { inner: client }) + } +} + +#[async_trait] +impl RSocket for RedisDao { + async fn request_response(&self, req: Payload) -> Result> { + let client = self.inner.clone(); + let mut conn = client.get_async_connection().await?; + let value: redis::RedisResult> = redis::cmd("GET") + .arg(&[req.data_utf8()]) + .query_async(&mut conn) + .await; + match value { + Ok(Some(value)) => Ok(Some(Payload::builder().set_data_utf8(&value).build())), + Ok(None) => Ok(None), + Err(e) => Err(e.into()), + } + } + + async fn metadata_push(&self, _req: Payload) -> Result<()> { + todo!() + } + + async fn fire_and_forget(&self, _req: Payload) -> Result<()> { + todo!() + } + + fn request_stream(&self, _req: Payload) -> Flux> { + todo!() + } + + fn request_channel(&self, _reqs: Flux>) -> Flux> { + todo!() + } } ``` From 7cee10cf724da1aef3b9b6c571108291b28c3606 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Tue, 12 Jan 2021 16:31:11 +0800 Subject: [PATCH 44/70] chore: use mkcert to generate TLS example certificates and keys (#38) --- examples/tls/README.md | 12 +++++++ examples/tls/cert.pem | 31 ----------------- examples/tls/client.rs | 2 +- examples/tls/foobar.com-key.pem | 28 +++++++++++++++ examples/tls/foobar.com.p12 | Bin 0 -> 2677 bytes examples/tls/foobar.com.pem | 25 ++++++++++++++ examples/tls/identity.p12 | Bin 4117 -> 0 bytes examples/tls/server.rs | 4 +-- scripts/generate-certificate.sh | 59 -------------------------------- 9 files changed, 68 insertions(+), 93 deletions(-) create mode 100644 examples/tls/README.md delete mode 100644 examples/tls/cert.pem create mode 100644 examples/tls/foobar.com-key.pem create mode 100644 examples/tls/foobar.com.p12 create mode 100644 examples/tls/foobar.com.pem delete mode 100644 examples/tls/identity.p12 delete mode 100755 scripts/generate-certificate.sh diff --git a/examples/tls/README.md b/examples/tls/README.md new file mode 100644 index 0000000..8234b63 --- /dev/null +++ b/examples/tls/README.md @@ -0,0 +1,12 @@ +# TLS Example + +## Generate Certificates and Keys + +1. Install [mkcert](https://github.com/FiloSottile/mkcert) +2. Generate keys: `mkcert foobar.com` +3. Generate `p12` file: `openssl pkcs12 -export -out foobar.com.p12 -inkey foobar.com-key.pem -in foobar.com.pem -password pass:foobar` + +## Run + +1. Start TLS Server: `RUST_LOG=info cargo run --example tls-server` +2. Start TLS Client: `RUST_LOG=info cargo run --example tls-client` diff --git a/examples/tls/cert.pem b/examples/tls/cert.pem deleted file mode 100644 index 20ad7d4..0000000 --- a/examples/tls/cert.pem +++ /dev/null @@ -1,31 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFUDCCAzigAwIBAgIJAJjWP27hY7PeMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV -BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX -aWRnaXRzIFB0eSBMdGQwHhcNMjEwMTA1MDMwODUzWhcNMjIwMTA1MDMwODUzWjBa -MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 -ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRMwEQYDVQQDDApmb29iYXIuY29tMIICIjAN -BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtv10GWc14Kyu94jmT/a52HEdTf9f -gSFc9fTiGIcvsHwGe5HU5tMEEpVmVQqMeWHMgIunHpAVbmu9dhZ/r256QiR+bU8o -Zzv6ShJ6gdYAv/j2MEu7sHFpFHWEaZmPgqbREHioerS8AMJwNLcFF47EKUsKlbJy -Yn7rsfDl1Vir3I5l2VOORmjNOap/++CNJf39oGN8yx6+6YUT+lcUY2GkI8BkXLRI -ITTYOnAsjnwtk9k2sHQaCMfmlQYr5FCDTi2A4MEWfBecJ8Logbt+E02ZaaMj5pSW -Q4oqpZUEzhYhUgNUahy1Gfeso9BZsFj056dn8qiaa61tV1vtFsnk2bHEU9HTu/NA -TwTLsRhWVqfOA04zT2V9OPcaO+shiMsY7JzivLFnBBsPeTC43e5Js1OZSeRr6Dbq -8jJ61p+f5DbBRHUFl3oZ0pz+8xYpusDHHzVPqE5izKS3fz2FNyK+OjJwEsNmSpNc -X4+g3YeZj3Oq4fs/vGu3y1IZq9wIR1pBSRosW+SOpPd9PBWhbF43fUa0k2kSI7Xc -BkDQbEWxY0jEY4vzvNOA2C5A3eg8DzvDpjGE13GeSzk3DsObwmugHWZaz/TK0KeI -7LWDCHkUBizublZ+htUHDZxTU5mXWhaU2tU/udz+4rPVymns8RZ+Omm3uOC4PuQo -g+ezrcaZwyZptv0CAwEAAaMuMCwwEwYDVR0lBAwwCgYIKwYBBQUHAwEwFQYDVR0R -BA4wDIIKZm9vYmFyLmNvbTANBgkqhkiG9w0BAQsFAAOCAgEAKj6H77fLp5jL/oEJ -qglaOaM4OHU4FbQ3mTPLTjeVrvcnoxavigZC++0FwEkNm9FEfA8fDDNsVgK4CTof -Jdsq10hkHVE44Y5WLJha4o50dvUczj0k4wV5BaZ0cC2aYwdRXVkSYVNa90951pDq -FBy75ltWUWnQ8tibU4tZPgg2sbMzWkcRJ5bJfmEFVbB930x6ofllVZx2h9wZERBp -otgtJzQ1+P+MZ5By2nF59gpKURbRyS06y5emuhs/7UF2E/ETvMTiyBgcRiASYqGO -2bcxvZ6J6zo93D2gEAUKrP2QVsE0o3oTtc3N5ix1lXegdi9AM4AGnzb8uDkjyJHn -J9ibW1pWPYey2DjArbcq1uSKzXtC+YVEdS7k6X91ksYrFZgjAporyhJbqISq+sJO -1gaTXu1VRNRhFVfJQjNVfA0ar+RHcx5xetdJKRglekGqGcBQfTFMNhLcGfuY16pe -qRzF9gwCqnX0c+tIl32IxCS4g6Pj/LBn3qCGE4sycWUz6+mwjGopFWK2gBGpj4M0 -Dvnv+c72QQKmijtpQX6tSn75MBhtG9hZD8jPpMyfIFfkhx71StZ4j1O+rvXQs7go -Nb9qJOug/jfSrDQl9D5FSlRaqX19fm7JxiK7+fSnh/WlMmBQfn/j/lJ/sSDcyAbb -KrQM79kml5Luw0QXo7yLtoYD93A= ------END CERTIFICATE----- diff --git a/examples/tls/client.rs b/examples/tls/client.rs index 6744a4b..799581d 100644 --- a/examples/tls/client.rs +++ b/examples/tls/client.rs @@ -10,7 +10,7 @@ use rsocket_rust_transport_tcp::TlsClientTransport; async fn main() -> Result<()> { env_logger::builder().format_timestamp_millis().init(); - let pem = include_bytes!("cert.pem"); + let pem = include_bytes!("foobar.com.pem"); let cert = native_tls::Certificate::from_pem(pem)?; let cx = native_tls::TlsConnector::builder() .add_root_certificate(cert) diff --git a/examples/tls/foobar.com-key.pem b/examples/tls/foobar.com-key.pem new file mode 100644 index 0000000..1e065b6 --- /dev/null +++ b/examples/tls/foobar.com-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDc0eGB4glOkrCq +3S1umHNuRahgLx26FnEhescnLvJFJ4365Vc9qC1k/4Zzjz+0Y2glFkBrebn5b7r6 +vhPD1ryGN50dtUtpV+JEBS7z/f9NdT/eAB7PeNYyg5AEO+hWuk+mXKBbeWd/bKz5 +XcWHcYTAar6XwhF8T1+f6U5SyJBZVdEFH2fRN6fUJWHkfzWnkOBDOfoCaN+rniVP +U+CvJaq4F13ehMOU4Jsp2YrX7PbE3F5fh19+HiZcFKj1aTZ5a+Po1nvmIroqXJPY +4wXlU52Kn6Vz+rh2e8lKY08L8wO0mpruN3FDVb7px3+dY0LSK0lsMN1Ncxa63bDc +wRKfTL+5AgMBAAECggEABdX2I7yZil4OFTXrMXUN9+gXXxNfsb9OFhhskviGppU5 +B1xwRczgBj9KiltKz7Wg1voTkcORyqnNQzsqwo42RUXK/TIBYDNWY33Pk9sumBl1 +KqTOK6WB46vebn420bPyzu67vi8jMRbqK1zzD3VMkNlBWDlkxOhEGrHLxBxQ1EuH +vLlKODwByMRMjozp8g9R4i+RIhLGP6HRFwaGPcDsKX5FBjFipeYH6mFFn4wqzg3p +qL636u5bmD6bOcrA2P7c42dD2DWiN/jhfJCSw5eBMzNXSBIJxPWgFx/fdUZLNb7G +XdTlNYFexnAntzTN9wP9aaNVE7Zr1vS8htGS2s2iQQKBgQDyymsosdRdfue0oWtp +GgkB5K8KINAQfpw/6FyYry/QjSSO6KYe2B61AkTo5LsOoxalGvmxWrojK6P1sCPn +hHZ4WcuEZqUtFxpzQJEVi8hJemSePofalPHYH5b0rie5msNPxtxsod/0uAlD4yyI +4mBta7mA79OLszylpaDbdFmKNQKBgQDo1XP1leUPr/tDmlxyP01Yh7bJzOrxHHGH +3USLW7lDo8o7rWJctr6svsIoCWWWNvNKUOnQL3hU/BZSQD+Y5aEwGfUz4WpF5Bfv +T0uI3HXtYb1SYZhu4Ql9xIWdmKhV626hYf7tzzHB8gyMOm64MInC7gc32dq7Tn2l +ly9XCcTv9QKBgDtqOcsdqaCvu7hCgGyaCHZEJmnOGdzPfyFMlcxvor3grH+kg3Ks +5ObbBU4RG427b4E8FrrGPyL4PQmU71Rq4CsXnmxqSiW8r6ZguKCTMpJ4t0LafpiJ +Np3zLRf3vpT3QLC3M54KByp2Fx5b67wb2gktAZqCFjzrwf2viKvrzzW5AoGAF7iv +kMTNypReYBvY8VbbtXpWOCclhJ0mP/ZeJmiY7nhAgWX/0HxZ3tWsiFG0xOIiVV77 +A1fixZ3NVGHxWM2EZ5ctcTS1FBvSCHKmunHjneTIWh1RX3KT+flMt6q289IBunV2 +eJoUcrMLbjoBz8g6MN75Y0pRy6WKjZVioFaBdwUCgYEAy4NrZ5HlST9lfbdTBwuu +VeV5s26dR6xBd0gFr8HanRZBfsNFGXbo11nvVrNa98vS3WsnNTLX68jTsbYbxvpz ++UhSliO7QZZF+vGvd6PUWg5HsxS6m8eBehAMRUX5Yw8/01LmqbjsKtkeLnR0QKsp +Ralg7LHgoCJU+uAl/x0rXUo= +-----END PRIVATE KEY----- diff --git a/examples/tls/foobar.com.p12 b/examples/tls/foobar.com.p12 new file mode 100644 index 0000000000000000000000000000000000000000..0689f2f7c885ac5f220375d5681c67cfd89c2d6d GIT binary patch literal 2677 zcmY+^c{me}9|v$_V@4`QZq0q0qcBG(IYM)lGB>&J`)npM!`wtna;?aH)JRz5CZU7m z=%BEeYmR<;p5O2H{r&#|s^$iKU!&OQ>A`ep z3^3!qUIIX+w@t4V&U$nim!jjNrR%1yrt_!x!L&ruY>WpVlM(NS55#HuW)+YAK!ryd zK62kFi%$@^@iSz!#lp;!-_Ov{)>$=8^R}j4AL~WI$d>fQ{e8%#srV|AcG3YC=T$(^ zyd*>RVTt$-c!NXyTmtKu)$^vZmg^4;6?VaK)AJY zZ2|pf?C#J^`nri2&Y_-cBeFi6$Jnm(&Al2=?-{e`OQ!Ksr$Vergu52Z0(1gaZl^G^ z_;3V&jJ#uquT#_XPwo=W@pi)VvZv%opb@cC);%HO)8)Y>cgi3}B>Qb*ZRjtRZV^UZ zF25>|g8s3hGPX-o1EZk}GQ9OQFmNi-FvjyUYn54Gjr?+l#;ME~HeXuKN=&y#%9O_@ zceyq8!-a>SD$WDflaw^)pLhZd_0LItsq`{uQ5GJ>EI|)*nv>8{XJrx2qGU zkc*FzYo}8y$^OyB83#7Z&KE#Ro{PEPTQNGdlVi7ca&Cn=hZ`{G{;uu#!!jcy_DFg; zAq1=07&VxBj)pVc@b-WzS#LTD&ULe+THC`o+QRmkJ(>)2s|}x2>u+gI0pBGUq?Og>!Osz*OOQNNd-CuppxB+vZAyK(e375Q& zlIS+i6axZfX?FTyw{<`)D4OFdRuU}|y-tp)9 zRbhZLC)S?#yP2zk!=7rDI)7XX$N+)P71I5N|kwriDI}CU5CQ1D84(h_b zE5|cY#JBrTfAP!{25%Nw#Ws2QhYF_P{f{rsJ7Qm!-= z#7%Z?fm{22q&%bDC^~2Eq1et43s-?-K)U|}SSbdi1jK;kPh#nl6K7=k4`&bn{fT?) zC*ZCApK=U;m7|**>2D4(S^ujX@I*&|VnqyLjj0(HnY3lojqBA}C{udLM8%{{$lDm$ zn8mv18^(Q;=B79|eJER?=PJq={bpria%n8mm`!bO4Y80m9w(dDTSYu;QaM`l*y`rS z_0en}3)gIJSQ-rer&G~c2qx#^>OCG1;fs3QxGI>a$Nn(tOS77#2=#{JYTlqLi`kT;lZfabNv z)~(hVNWNO)+S;yl*`V2M`1(60JK&Zcgu(CZm3wB)TZ)_2;=i^mk%SO~=LY(g3}YWl ziZk-s;5C=;t+@vr{H87LW=k{$j;-}T^gx~m>}^3;Td4C2FtmMYd-F_?-RUbFF(a<} zq|P2VO$6%HI}ZR4e1BDA3HF46t2Z#TYPTTtlaGZK-@}4=JnH-&s&Mnj@EwdZnkiJ8 z+ZNAaLx-)G*#$CPS*<0tbK`jm9G>NZX@rda@R%GhqnuJ4dm-8(Y{JFV{r%_-^+n3G zBl8tGfJ6B-=(^>CKRd4KeuCk4dM2litk68~iXC+?UvO3I;qEW_aVI7nHAkxC0E6id z5OP^LwCnBt;#XG`wjLgZ99@ZhiV!ZXg|;Qe?UH*O*{Y4p=@X|A6&~Sx^(akm&)(Pj z^cTEn6+&TI-6THM!8IjxM0tpS)FX#66d_*ld|7`RRz5-cqj_!$-mq)Uo~dU&M9~oY znJL{AJNfT$A^n4Z&24d&Fk?LD#OG)&#RI?a$k)5H z%s9%7?#0?B&u6Ojq(6Mue(*}#XA!0C6rw-jZe@M?MQ5|XwJOXIs0VH0n`K98%-uEy z?$1zVEhxd0uCHI27Axc3=1>^d)BH6#U&x6SeGGSU2t(~xQ0iQgr5~*w{4fl#0O0#d zEv>@e+@GB22K=Sh=LGJSaT|B8NofL+0>j>g*W_dfdVerer% z0W5(H<&?YK$Z~F8OX=4oqyqJ_;Yy`-|&&qgjj5S@OatiB}Fl~ z$bWTY=2YYYLK*Mm5w)`4Tr}Ssdfn@6JoMfVoeWom!{E$}AQ?6WdR`D65Q^oO(s(>0 ft~hr0w%_Kh2+F~O+$bQ}cL(wDNg_n+uaf@)s{iXW literal 0 HcmV?d00001 diff --git a/examples/tls/foobar.com.pem b/examples/tls/foobar.com.pem new file mode 100644 index 0000000..58d4ebe --- /dev/null +++ b/examples/tls/foobar.com.pem @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIELzCCApegAwIBAgIRAL59MTynwUpUEUR3vAJXA5wwDQYJKoZIhvcNAQELBQAw +dTEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMSUwIwYDVQQLDBxjYWl3 +QG1hcnMubG9jYWwgKFdlaXdlaSBDYWkpMSwwKgYDVQQDDCNta2NlcnQgY2Fpd0Bt +YXJzLmxvY2FsIChXZWl3ZWkgQ2FpKTAeFw0yMTAxMTIwODA0NTZaFw0yMzA0MTIw +ODA0NTZaMFAxJzAlBgNVBAoTHm1rY2VydCBkZXZlbG9wbWVudCBjZXJ0aWZpY2F0 +ZTElMCMGA1UECwwcY2Fpd0BtYXJzLmxvY2FsIChXZWl3ZWkgQ2FpKTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBANzR4YHiCU6SsKrdLW6Yc25FqGAvHboW +cSF6xycu8kUnjfrlVz2oLWT/hnOPP7RjaCUWQGt5uflvuvq+E8PWvIY3nR21S2lX +4kQFLvP9/011P94AHs941jKDkAQ76Fa6T6ZcoFt5Z39srPldxYdxhMBqvpfCEXxP +X5/pTlLIkFlV0QUfZ9E3p9QlYeR/NaeQ4EM5+gJo36ueJU9T4K8lqrgXXd6Ew5Tg +mynZitfs9sTcXl+HX34eJlwUqPVpNnlr4+jWe+Yiuipck9jjBeVTnYqfpXP6uHZ7 +yUpjTwvzA7Samu43cUNVvunHf51jQtIrSWww3U1zFrrdsNzBEp9Mv7kCAwEAAaNf +MF0wDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB8GA1UdIwQY +MBaAFIMrc/qDTdodpyMSPxDVH/RwVj39MBUGA1UdEQQOMAyCCmZvb2Jhci5jb20w +DQYJKoZIhvcNAQELBQADggGBAG5BOYGqum7g0Bc8Z8gxTrkUyzd1e9D5cNLwmYm6 +G+6/xfH6NM4ooQo5ek7GclUN5nkU0ZF85ElqQawR6SxH7C9wZT1s0HL7bOXq49kJ +Az2obJjyyap+sWNBnTcoKW/m9uc5ZSkKaI07AvWg4Uy16xxXWocN7zt3iEdgvTiE +953MFPMor5TgdgJScUuLh8OQrs+qX3AYKvl1wPoFeKqO2k9HdVu00uV7+x0LxtSU +aH0fbeXS1KKQARq6Xa1L69iUUcOh3RIMTLnQNMmb6F4oMWLERvwsI5qZ9FWGi0e/ +lQL/gGmNQSiihvTIC/oaMaIQyCrgJHYcXSB8RyPy4PvaWG6dVR0M8H/mtiU75U6j +7Z4Hwr74WhwY1wqIjnwL/jtVAyzyL8Yj9YkrYwditNYiDr3ciCDfxVOnTYK8XoQc +v0RJ/cPlJji0VOTXV+ebIkTELjD27A2dXif+4hKfctehULsEVkUrY8jn36YXfw2g +SP4kpOTQxpbmjW7KbVOmneIrsA== +-----END CERTIFICATE----- diff --git a/examples/tls/identity.p12 b/examples/tls/identity.p12 deleted file mode 100644 index b0c9e5e5d9977157970bc9aeba885e75e0233a4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4117 zcmY+GWmFUlw}lycn4m*ay1Q{m>6Q|u8-`(!msAkxp@t3-fsq(ON@V~+T0&B~Q@SK2 z6u7=?-Fv@#f1GvJdiFZ!=iXZ^f`SqsKp+-DK1~c1h|!L@fB;AUmRC9*0D)i&ylj4O%5Y_5{ zcT0p!^!({_MaZHbsSh9Y>)}?6IM&ZSxHR@?i};Yj05$F~eIyO)OjNSLD~#x+D=9?R ze}t_-bb~A1x!5*Qi7|c>RVm78Lg>VE7zpLT#>sP^c2M)BK)W#@U3p4AFI9qNI~hS` z=Uf50g1{R2Q~vmD&VFQY^g!TR?C)7L_iV}id>xj46*bd^p!MqEJI?e!QFmi);$k?3 zd8)4_ArH5|7oHjSkyc{I54S%rgi?%4W_SzlN>udxGei~K25x-M%8@n!(1q^sEBr9B zlP-7T7x8YrF}Q_AX1+0aZy?p`p>U8Q$ph}j zqMCIQ@Ts`$`;OXPuO3Jk^9bG#mJvJ9=fUU1$eyiYhi>Cnl`(ZcH&&n3>Lxfr@R@>2 zV}KtvH4J@_tMbwJ6YWW9i>5EQi0vzOEXaKXwRsZiZ$isLE#IQ;(*_CX-3VeJ2nD<# zDa+nz^+kRq4sOV{j6uDv@Ox=-ozbfoVZ2VwtZsSAHBWT4#ch%X-}*}=$MAP9<5iV` z%YVS0e~)f{Kq1ZUE#2`>_wi+_^2>=8#|3UYA_UhR&Mjz#gVmMfXgc|@fZ1tnCrzw- zo_d5gzk9;bEo)ClfPGA&&-X55W~IWr*Z!p|KDcwd16?U)6dHE8ux_zoH1S*)uW-Tv zAsusX37YIB^vxOnbC(fg!jH`3ujCdzpjJ{Yn2W#Av z2yhtv9%x8F^lp#T6YLA}9@Z%x^ux7WSiZ9%c*>b?Gj`V*2^iUwr2oW|=qE<7nfATn zdB45zysavog;1cgmd$~0-Iynl&*YpsOy?Et4Ap54JVP5v!qin#Yo@3q!73U^TKEoj zu?t^2SqhJsw>LqA+uqS>I@kZW=&@Lw0?Fkg%`(my&;KX~Ks9wBgc}ufE!1|A9hK2; zn7)|I)L2KtF*z~tf>IW+QSy`oK}{EXGI#rU_9PxXGG7V#cm|WRs5j1*ACE3+8H}D>;c$6@B67oG>lwB_jlRYP(-5Aq1|zvTkl>N3XFw z0edd`*vp5UfQ$laTLk^n^TKP&{WyB3SD4rZXzvVRiW?tdA6#qQlCOpFJG8r79jol%Hs2 z?cG$VWJ8eOWsdJpp>D0rDZ(x;tSod0OP;*KX$pY&k>iiHjEa4Ldw>0^y+ib>~@Q$HKhj%SZ0j6 zj=DMHKY36-pUXg${gY^3(1c7;n}rT?vM+DiS-6sAW4YC#8U&Yn5`{BdV$Ka&9Y-Mm zkF+S=l-NS&kQT%Z;e#6g8JVlsSi~_P>0K9=$gXr<~l9 zrDS9|XJ~-5083Q7CUq3Bi$F51vXb$@dq^g?81M3d7&I^R(^F#`g$V z{s4p!7gggTjxURbA0h1NANf+o3^3Tq^WN)jRY&dS3Wee?FjqGkB>649R%mfoA-C;c zaNv&6v1w(P#b8<2Y8vUt;lPNvQED*)f;U$o$U5Vf?TF=2i8TEH!|*hZ&`x9A0VU5y z)w*6&zeBQ%3^1g5zfY2mvU(3)82BMkIPu&ggA;41`9Qa#c`(X8%ylx38(Vi7JVbvcQJ{Y~{NA_%|`!S1o{flNbdHb?81eK9W|wa%u=*?e^)bQ%l-JG~C6- zoZj%0?+qj>M)pX3*B|EBfu~b)1$k26Z6iu47aj-~uSO!13*O92XarZ|^7T=-%Zyl!sn=9ucc(c?~yx4-A<1Plz84U4((Hr~@uA9@MDy$3;+nIBQ&^QjKIxR2JC1 z5P9CxV;6W-wL}rnivkjQprN$ep}|}HRN29?WI${0T0Iv2N(IPQv#N^&96J-P>Zd(i zGb=Duyo%?8DSMNg{HW)rupuS#9Jd%{pl1%1&Md3J`lpGd&;%JYw73Y++PWvrNm{as z3zXI~u=!$^NIbbuiwYfWb*OS0J0UO!two(zP>t0nsTn4!8)n1F-e+O3{n@=j|0r5o z1qHxP1hB~_;kP&Wg;__<5@v25#(ceeEm>Aa_v+W&)?Y+OD_p1(2#>qWYchMvg3i7P zinzi8)CowlXSXKzmx-b@R97suIELpFbqjl`YDcOdu`9i_RY-WDL-0^1M~_*-XGNkn zJzn}OF<*SALgE@{A2wU-QWbS;9fqaJd>r>AcV}45KwV+{)xsk%b}32ZR% z3Kh3wHT-Z6YfAEMk1?ueOa6E#GS+4^nNgAmG^lztm^#B}EI}2&%F81+CF~gt!%7@e zw6k8bQfWs<`V%GW_Pxe)4~sJ@g9N+xB5#@tF2}$U<%P#mG}U~di+-6sWx1m}6SgPu z;Ml{-@ZQQPC!My;9g7cjOP`CZQeBtR%bq~jE>z)lVzq4R5^A5w0^W?dQfSakz+@Vl z92iSX)$|IRZ{IW})o==}zK}IyOy&P>wK-oB9aj}G*veH-*i`U7S!r^Qek$oabGr(pViX_8UWYz z`ANd!^|%irxTNXouKe_vLB-(N_VBA0v0gm(kDt@Oz!RK#zU-jOO%%Xtxdb8UwDtSp zJKH0zp;!d)nG!pqm@KkLp za~OX6+;cIG;RJC=Kuc35n0+ce7j3c06^@h70Z{k(WcTYi=Nn7!MCvZLf9LSyzs?Uc7I>`*>WwlI=eHy?WE5Ys1?`5Y z8v;m?S@Fh38KHd8k?aa2WvV&LwUuqlseazK#8thp&8PZ3xns7ZTPn>vMO`0Xe@9D& zJTTM2rOez}?AyYlzW`Cf_+ZNeEiQu_y+$(=tz{~WEK;W(vgEhy1KkB&co+kZP6*Qs zPm3C;y#YF#@8^!t^JicusuKm zPsA=QsdI&S0(V$f_qjPdsDm$_-up?%c7Cp=dWmL=GnfnaeRSwP6DOF@z7@49R?868 z4DRVz&>jq$bx>mD8GyiRA{{>lrk#_(9 diff --git a/examples/tls/server.rs b/examples/tls/server.rs index 28d5544..b77a6e4 100644 --- a/examples/tls/server.rs +++ b/examples/tls/server.rs @@ -11,8 +11,8 @@ use rsocket_rust_transport_tcp::TlsServerTransport; async fn main() -> Result<()> { env_logger::builder().format_timestamp_millis().init(); - let der = include_bytes!("identity.p12"); - let cert = native_tls::Identity::from_pkcs12(der, "mypass")?; + let der = include_bytes!("foobar.com.p12"); + let cert = native_tls::Identity::from_pkcs12(der, "foobar")?; RSocketFactory::receive() .acceptor(Box::new(|setup, _socket| { info!("connection established: {:?}", setup); diff --git a/scripts/generate-certificate.sh b/scripts/generate-certificate.sh deleted file mode 100755 index 4c43490..0000000 --- a/scripts/generate-certificate.sh +++ /dev/null @@ -1,59 +0,0 @@ -# https://github.com/tokio-rs/tls/blob/master/tokio-native-tls/scripts/generate-certificate.sh - -#!/bin/bash -set -e - -cd $1 - -# prepare config file for root CA generation -cat <> root.cnf -[ req ] -distinguished_name = req_dn -[ req_dn ] -[ v3_ca ] -basicConstraints = CA:TRUE -keyUsage = digitalSignature, nonRepudiation, keyCertSign, cRLSign -subjectKeyIdentifier = hash -authorityKeyIdentifier = keyid:always -EOF - -ROOT_CA_KEY=root-ca.key.pem -ROOT_CA=root-ca.pem -ROOT_CA_DER=root-ca.der - -echo "Generate root CA key" -openssl genrsa -out $ROOT_CA_KEY 4096 - -echo "Generate root CA certificate" -openssl req -x509 -new -key $ROOT_CA_KEY -out $ROOT_CA -days 365 -SHA256 -subj "/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd" -config root.cnf -extensions v3_ca -openssl x509 -outform der -in $ROOT_CA -out $ROOT_CA_DER - -rm root.cnf - -# prepare config file for server certificate generation -cat <> server.cnf -extendedKeyUsage=serverAuth -subjectAltName = @alt_names -[alt_names] -DNS.1 = foobar.com -EOF - - -SERVER_KEY=server.key.pem -SERVER_CERT=cert.pem -SERVER_CERT_DER=cert.der -IDENTITY=identity.p12 -PASSPHRASE=mypass - -echo "Generate server key" -openssl genrsa -out $SERVER_KEY 4096 - -echo "Generate server certificate" -openssl req -out server.csr -key $SERVER_KEY -new -days 365 -SHA256 -subj "/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=foobar.com" -openssl x509 -req -days 365 -SHA256 -in server.csr -CA $ROOT_CA -CAkey $ROOT_CA_KEY -CAcreateserial -out $SERVER_CERT -extfile server.cnf -openssl x509 -outform der -in $SERVER_CERT -out $SERVER_CERT_DER - -openssl pkcs12 -export -out $IDENTITY -inkey $SERVER_KEY -in $SERVER_CERT -passout pass:$PASSPHRASE - -rm server.csr -rm server.cnf From a65a0561b287dc96cb833da9d5dff17c14dbd497 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Wed, 13 Jan 2021 12:18:04 +0800 Subject: [PATCH 45/70] chore(rustfmt): optimize import (#39) --- examples/echo.rs | 3 ++- examples/qps.rs | 11 +++++----- justfile | 2 +- rsocket-messaging/src/requester.rs | 10 ++++++---- rsocket-test/tests/test_clients.rs | 5 +++-- rsocket-transport-tcp/src/client/tcp.rs | 6 ++++-- rsocket-transport-tcp/src/client/tls.rs | 6 ++++-- rsocket-transport-tcp/src/client/uds.rs | 5 +++-- rsocket-transport-tcp/src/connection/codec.rs | 3 ++- rsocket-transport-tcp/src/connection/tcp.rs | 5 ++--- rsocket-transport-tcp/src/connection/tls.rs | 3 ++- rsocket-transport-tcp/src/connection/uds.rs | 3 ++- rsocket-transport-tcp/src/lib.rs | 7 +++---- rsocket-transport-tcp/src/server/tcp.rs | 6 ++++-- rsocket-transport-tcp/src/server/tls.rs | 6 ++++-- rsocket-transport-tcp/src/server/uds.rs | 5 +++-- rsocket-transport-wasm/src/client.rs | 10 ++++++---- rsocket-transport-wasm/src/misc.rs | 3 ++- rsocket-transport-websocket/src/client.rs | 6 ++++-- rsocket-transport-websocket/src/connection.rs | 3 ++- rsocket-transport-websocket/src/server.rs | 6 ++++-- rsocket/src/core/server.rs | 18 +++++++++-------- rsocket/src/error.rs | 1 + rsocket/src/extension/composite.rs | 10 ++++++---- rsocket/src/extension/routing.rs | 3 ++- rsocket/src/frame/error.rs | 6 ++++-- rsocket/src/frame/keepalive.rs | 3 ++- rsocket/src/frame/lease.rs | 3 ++- rsocket/src/frame/metadata_push.rs | 3 ++- rsocket/src/frame/mod.rs | 3 ++- rsocket/src/frame/payload.rs | 3 ++- rsocket/src/frame/request_channel.rs | 3 ++- rsocket/src/frame/request_fnf.rs | 3 ++- rsocket/src/frame/request_n.rs | 3 ++- rsocket/src/frame/request_response.rs | 3 ++- rsocket/src/frame/request_stream.rs | 3 ++- rsocket/src/frame/resume.rs | 3 ++- rsocket/src/frame/resume_ok.rs | 3 ++- rsocket/src/frame/setup.rs | 6 ++++-- rsocket/src/frame/utils.rs | 3 ++- rsocket/src/frame/version.rs | 3 ++- rsocket/src/payload/normal.rs | 3 ++- rsocket/src/payload/setup.rs | 6 ++++-- rsocket/src/prelude.rs | 3 ++- rsocket/src/spi.rs | 10 ++++++---- rsocket/src/transport/fragmentation.rs | 9 ++++++--- rsocket/src/transport/misc.rs | 3 ++- rsocket/src/transport/socket.rs | 20 ++++++++++--------- rsocket/src/utils.rs | 18 +++++++++-------- rustfmt.toml | 2 ++ 50 files changed, 169 insertions(+), 105 deletions(-) diff --git a/examples/echo.rs b/examples/echo.rs index 3349b85..41fb400 100644 --- a/examples/echo.rs +++ b/examples/echo.rs @@ -1,6 +1,8 @@ #[macro_use] extern crate log; +use std::fs; + use clap::{App, Arg, SubCommand}; use rsocket_rust::prelude::*; use rsocket_rust::transport::Connection; @@ -10,7 +12,6 @@ use rsocket_rust_transport_tcp::{ TcpClientTransport, TcpServerTransport, UnixClientTransport, UnixServerTransport, }; use rsocket_rust_transport_websocket::{WebsocketClientTransport, WebsocketServerTransport}; -use std::fs; enum RequestMode { FNF, diff --git a/examples/qps.rs b/examples/qps.rs index ead2378..920561b 100644 --- a/examples/qps.rs +++ b/examples/qps.rs @@ -1,17 +1,18 @@ #[macro_use] extern crate log; +use std::sync::{ + atomic::{AtomicU32, Ordering}, + Arc, +}; +use std::time::SystemTime; + use clap::{App, Arg}; use rsocket_rust::prelude::*; use rsocket_rust::transport::{Connection, Transport}; use rsocket_rust::Result; use rsocket_rust_transport_tcp::{TcpClientTransport, UnixClientTransport}; use rsocket_rust_transport_websocket::WebsocketClientTransport; -use std::sync::{ - atomic::{AtomicU32, Ordering}, - Arc, -}; -use std::time::SystemTime; use tokio::sync::{oneshot, Notify}; async fn connect( diff --git a/justfile b/justfile index 9bfdf60..36b565b 100644 --- a/justfile +++ b/justfile @@ -9,7 +9,7 @@ test: lint: @cargo clippy fmt: - @cargo fmt + @cargo +nightly fmt echo: @RUST_LOG=release cargo run --release --example echo -- serve tcp://127.0.0.1:7878 bench: diff --git a/rsocket-messaging/src/requester.rs b/rsocket-messaging/src/requester.rs index 65dca41..088141a 100644 --- a/rsocket-messaging/src/requester.rs +++ b/rsocket-messaging/src/requester.rs @@ -1,4 +1,7 @@ -use super::misc::{self, marshal, unmarshal}; +use std::collections::LinkedList; +use std::net::SocketAddr; +use std::sync::Arc; + use bytes::{Bytes, BytesMut}; use rsocket_rust::extension::{CompositeMetadata, MimeType, RoutingMetadata}; use rsocket_rust::prelude::*; @@ -7,11 +10,10 @@ use rsocket_rust::{error::RSocketError, Result}; use rsocket_rust_transport_tcp::TcpClientTransport; use rsocket_rust_transport_websocket::WebsocketClientTransport; use serde::{de::DeserializeOwned, Serialize}; -use std::collections::LinkedList; -use std::net::SocketAddr; -use std::sync::Arc; use url::Url; +use super::misc::{self, marshal, unmarshal}; + type FnMetadata = Box Result<(MimeType, Vec)>>; type FnData = Box Result>>; type PreflightResult = Result<(Payload, MimeType, Arc>)>; diff --git a/rsocket-test/tests/test_clients.rs b/rsocket-test/tests/test_clients.rs index 50d99c6..1181cbc 100644 --- a/rsocket-test/tests/test_clients.rs +++ b/rsocket-test/tests/test_clients.rs @@ -1,6 +1,9 @@ #[macro_use] extern crate log; +use std::thread::sleep; +use std::time::Duration; + use futures::stream; use rsocket_rust::prelude::*; use rsocket_rust::utils::EchoRSocket; @@ -9,8 +12,6 @@ use rsocket_rust_transport_tcp::{ TcpClientTransport, TcpServerTransport, UnixClientTransport, UnixServerTransport, }; use rsocket_rust_transport_websocket::{WebsocketClientTransport, WebsocketServerTransport}; -use std::thread::sleep; -use std::time::Duration; use tokio::runtime::Runtime; fn init() { diff --git a/rsocket-transport-tcp/src/client/tcp.rs b/rsocket-transport-tcp/src/client/tcp.rs index 9896dbe..72ba80e 100644 --- a/rsocket-transport-tcp/src/client/tcp.rs +++ b/rsocket-transport-tcp/src/client/tcp.rs @@ -1,9 +1,11 @@ -use crate::{connection::TcpConnection, misc::parse_tcp_addr}; +use std::net::SocketAddr; + use rsocket_rust::async_trait; use rsocket_rust::{error::RSocketError, transport::Transport, Result}; -use std::net::SocketAddr; use tokio::net::TcpStream; +use crate::{connection::TcpConnection, misc::parse_tcp_addr}; + #[derive(Debug)] enum Connector { Direct(TcpStream), diff --git a/rsocket-transport-tcp/src/client/tls.rs b/rsocket-transport-tcp/src/client/tls.rs index 3bc21a1..943976e 100644 --- a/rsocket-transport-tcp/src/client/tls.rs +++ b/rsocket-transport-tcp/src/client/tls.rs @@ -1,10 +1,12 @@ -use crate::connection::TlsConnection; +use std::net::SocketAddr; + use rsocket_rust::async_trait; use rsocket_rust::{error::RSocketError, transport::Transport, Result}; -use std::net::SocketAddr; use tokio::net::TcpStream; use tokio_native_tls::{TlsConnector, TlsStream}; +use crate::connection::TlsConnection; + #[derive(Debug)] enum Connector { Direct(TlsStream), diff --git a/rsocket-transport-tcp/src/client/uds.rs b/rsocket-transport-tcp/src/client/uds.rs index 1efd9f3..9d033fd 100644 --- a/rsocket-transport-tcp/src/client/uds.rs +++ b/rsocket-transport-tcp/src/client/uds.rs @@ -1,9 +1,10 @@ -use crate::connection::UnixConnection; -use crate::misc::parse_uds_addr; use rsocket_rust::async_trait; use rsocket_rust::{error::RSocketError, transport::Transport, Result}; use tokio::net::UnixStream; +use crate::connection::UnixConnection; +use crate::misc::parse_uds_addr; + #[derive(Debug)] enum Connector { Direct(UnixStream), diff --git a/rsocket-transport-tcp/src/connection/codec.rs b/rsocket-transport-tcp/src/connection/codec.rs index 99abce2..c082d5f 100644 --- a/rsocket-transport-tcp/src/connection/codec.rs +++ b/rsocket-transport-tcp/src/connection/codec.rs @@ -1,7 +1,8 @@ +use std::io::{Error, ErrorKind}; + use bytes::{Buf, BytesMut}; use rsocket_rust::frame::Frame; use rsocket_rust::utils::{u24, Writeable}; -use std::io::{Error, ErrorKind}; use tokio_util::codec::{Decoder, Encoder}; pub struct LengthBasedFrameCodec; diff --git a/rsocket-transport-tcp/src/connection/tcp.rs b/rsocket-transport-tcp/src/connection/tcp.rs index 6b0b4ce..b5144f9 100644 --- a/rsocket-transport-tcp/src/connection/tcp.rs +++ b/rsocket-transport-tcp/src/connection/tcp.rs @@ -1,9 +1,8 @@ use futures::{SinkExt, StreamExt}; -use tokio::net::TcpStream; -use tokio_util::codec::Framed; - use rsocket_rust::error::RSocketError; use rsocket_rust::transport::{Connection, FrameSink, FrameStream}; +use tokio::net::TcpStream; +use tokio_util::codec::Framed; use super::codec::LengthBasedFrameCodec; diff --git a/rsocket-transport-tcp/src/connection/tls.rs b/rsocket-transport-tcp/src/connection/tls.rs index 5d9f032..47e142d 100644 --- a/rsocket-transport-tcp/src/connection/tls.rs +++ b/rsocket-transport-tcp/src/connection/tls.rs @@ -1,4 +1,3 @@ -use super::codec::LengthBasedFrameCodec; use futures::{SinkExt, StreamExt}; use rsocket_rust::error::RSocketError; use rsocket_rust::transport::{Connection, FrameSink, FrameStream}; @@ -6,6 +5,8 @@ use tokio::net::TcpStream; use tokio_native_tls::TlsStream; use tokio_util::codec::Framed; +use super::codec::LengthBasedFrameCodec; + #[derive(Debug)] pub struct TlsConnection { stream: TlsStream, diff --git a/rsocket-transport-tcp/src/connection/uds.rs b/rsocket-transport-tcp/src/connection/uds.rs index 8b454d3..efc512a 100644 --- a/rsocket-transport-tcp/src/connection/uds.rs +++ b/rsocket-transport-tcp/src/connection/uds.rs @@ -1,10 +1,11 @@ -use super::codec::LengthBasedFrameCodec; use futures::{SinkExt, StreamExt}; use rsocket_rust::error::RSocketError; use rsocket_rust::transport::{Connection, FrameSink, FrameStream}; use tokio::net::UnixStream; use tokio_util::codec::Framed; +use super::codec::LengthBasedFrameCodec; + #[derive(Debug)] pub struct UnixConnection { stream: UnixStream, diff --git a/rsocket-transport-tcp/src/lib.rs b/rsocket-transport-tcp/src/lib.rs index 50b535e..dcb4f19 100644 --- a/rsocket-transport-tcp/src/lib.rs +++ b/rsocket-transport-tcp/src/lib.rs @@ -8,15 +8,14 @@ mod connection; mod misc; mod server; -pub use client::{TcpClientTransport, UnixClientTransport}; -pub use connection::{TcpConnection, UnixConnection}; -pub use server::{TcpServerTransport, UnixServerTransport}; - #[cfg(feature = "tls")] pub use client::TlsClientTransport; +pub use client::{TcpClientTransport, UnixClientTransport}; #[cfg(feature = "tls")] pub use connection::TlsConnection; +pub use connection::{TcpConnection, UnixConnection}; #[cfg(feature = "tls")] pub use server::TlsServerTransport; +pub use server::{TcpServerTransport, UnixServerTransport}; #[cfg(feature = "tls")] pub use tokio_native_tls; diff --git a/rsocket-transport-tcp/src/server/tcp.rs b/rsocket-transport-tcp/src/server/tcp.rs index 0ab415e..085307c 100644 --- a/rsocket-transport-tcp/src/server/tcp.rs +++ b/rsocket-transport-tcp/src/server/tcp.rs @@ -1,9 +1,11 @@ -use crate::{client::TcpClientTransport, misc::parse_tcp_addr}; +use std::net::SocketAddr; + use rsocket_rust::async_trait; use rsocket_rust::{error::RSocketError, transport::ServerTransport, Result}; -use std::net::SocketAddr; use tokio::net::TcpListener; +use crate::{client::TcpClientTransport, misc::parse_tcp_addr}; + #[derive(Debug)] pub struct TcpServerTransport { addr: SocketAddr, diff --git a/rsocket-transport-tcp/src/server/tls.rs b/rsocket-transport-tcp/src/server/tls.rs index b92f3b8..b299fcf 100644 --- a/rsocket-transport-tcp/src/server/tls.rs +++ b/rsocket-transport-tcp/src/server/tls.rs @@ -1,10 +1,12 @@ -use crate::client::TlsClientTransport; +use std::net::SocketAddr; + use rsocket_rust::async_trait; use rsocket_rust::{error::RSocketError, transport::ServerTransport, Result}; -use std::net::SocketAddr; use tokio::net::TcpListener; use tokio_native_tls::TlsAcceptor; +use crate::client::TlsClientTransport; + pub struct TlsServerTransport { addr: SocketAddr, listener: Option, diff --git a/rsocket-transport-tcp/src/server/uds.rs b/rsocket-transport-tcp/src/server/uds.rs index 24618e2..991e04f 100644 --- a/rsocket-transport-tcp/src/server/uds.rs +++ b/rsocket-transport-tcp/src/server/uds.rs @@ -1,9 +1,10 @@ -use crate::client::UnixClientTransport; -use crate::misc::parse_uds_addr; use rsocket_rust::async_trait; use rsocket_rust::{error::RSocketError, transport::ServerTransport, Result}; use tokio::net::UnixListener; +use crate::client::UnixClientTransport; +use crate::misc::parse_uds_addr; + #[derive(Debug)] pub struct UnixServerTransport { addr: String, diff --git a/rsocket-transport-wasm/src/client.rs b/rsocket-transport-wasm/src/client.rs index 62431d9..89a00df 100644 --- a/rsocket-transport-wasm/src/client.rs +++ b/rsocket-transport-wasm/src/client.rs @@ -1,4 +1,7 @@ -use super::connection::WebsocketConnection; +use std::cell::RefCell; +use std::future::Future; +use std::rc::Rc; + use async_trait::async_trait; use bytes::BytesMut; use futures_channel::{mpsc, oneshot}; @@ -8,13 +11,12 @@ use rsocket_rust::frame::Frame; use rsocket_rust::transport::Transport; use rsocket_rust::utils::Writeable; use rsocket_rust::{error::RSocketError, Result}; -use std::cell::RefCell; -use std::future::Future; -use std::rc::Rc; use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; use web_sys::{ErrorEvent, Event, FileReader, MessageEvent, ProgressEvent, WebSocket}; +use super::connection::WebsocketConnection; + pub struct WebsocketClientTransport { url: String, } diff --git a/rsocket-transport-wasm/src/misc.rs b/rsocket-transport-wasm/src/misc.rs index 48b6a73..c0b08ad 100644 --- a/rsocket-transport-wasm/src/misc.rs +++ b/rsocket-transport-wasm/src/misc.rs @@ -1,10 +1,11 @@ -use super::client::WebsocketClientTransport; use js_sys::{Promise, Uint8Array}; use rsocket_rust::prelude::*; use rsocket_rust::Client; use wasm_bindgen::prelude::{wasm_bindgen, JsValue}; use wasm_bindgen_futures::future_to_promise; +use super::client::WebsocketClientTransport; + #[derive(Serialize, Deserialize)] pub struct JsPayload { data: Option>, diff --git a/rsocket-transport-websocket/src/client.rs b/rsocket-transport-websocket/src/client.rs index 377d61a..512338b 100644 --- a/rsocket-transport-websocket/src/client.rs +++ b/rsocket-transport-websocket/src/client.rs @@ -1,10 +1,12 @@ -use super::connection::WebsocketConnection; -use rsocket_rust::{async_trait, error::RSocketError, transport::Transport, Result}; use std::net::SocketAddr; + +use rsocket_rust::{async_trait, error::RSocketError, transport::Transport, Result}; use tokio::net::TcpStream; use tokio_tungstenite::{accept_async, connect_async}; use url::Url; +use super::connection::WebsocketConnection; + #[derive(Debug)] pub(crate) enum Connector { Direct(TcpStream), diff --git a/rsocket-transport-websocket/src/connection.rs b/rsocket-transport-websocket/src/connection.rs index eff31d2..ea66d62 100644 --- a/rsocket-transport-websocket/src/connection.rs +++ b/rsocket-transport-websocket/src/connection.rs @@ -1,3 +1,5 @@ +use std::result::Result; + use bytes::{BufMut, BytesMut}; use futures::stream::SplitSink; use futures::{Sink, SinkExt, StreamExt}; @@ -7,7 +9,6 @@ use rsocket_rust::{ transport::{Connection, FrameSink, FrameStream}, utils::Writeable, }; -use std::result::Result; use tokio::net::TcpStream; use tokio_tungstenite::{ tungstenite::{Error as WsError, Message}, diff --git a/rsocket-transport-websocket/src/server.rs b/rsocket-transport-websocket/src/server.rs index c77a995..e562534 100644 --- a/rsocket-transport-websocket/src/server.rs +++ b/rsocket-transport-websocket/src/server.rs @@ -1,8 +1,10 @@ -use super::client::WebsocketClientTransport; -use rsocket_rust::{async_trait, error::RSocketError, transport::ServerTransport, Result}; use std::net::SocketAddr; + +use rsocket_rust::{async_trait, error::RSocketError, transport::ServerTransport, Result}; use tokio::net::TcpListener; +use super::client::WebsocketClientTransport; + const WS_PROTO: &str = "ws://"; #[derive(Debug)] diff --git a/rsocket/src/core/server.rs b/rsocket/src/core/server.rs index c81642e..deb4dfb 100644 --- a/rsocket/src/core/server.rs +++ b/rsocket/src/core/server.rs @@ -1,3 +1,13 @@ +use std::error::Error; +use std::future::Future; +use std::marker::PhantomData; +use std::net::SocketAddr; +use std::pin::Pin; +use std::sync::Arc; + +use futures::{SinkExt, StreamExt}; +use tokio::sync::mpsc; + use crate::error::RSocketError; use crate::frame::{self, Frame}; use crate::payload::SetupPayload; @@ -6,14 +16,6 @@ use crate::spi::{RSocket, ServerResponder}; use crate::transport::{Connection, DuplexSocket, ServerTransport, Splitter, Transport, MIN_MTU}; use crate::utils::EmptyRSocket; use crate::Result; -use futures::{SinkExt, StreamExt}; -use std::error::Error; -use std::future::Future; -use std::marker::PhantomData; -use std::net::SocketAddr; -use std::pin::Pin; -use std::sync::Arc; -use tokio::sync::mpsc; pub struct ServerBuilder { transport: Option, diff --git a/rsocket/src/error.rs b/rsocket/src/error.rs index 3aaf645..fbbe75d 100644 --- a/rsocket/src/error.rs +++ b/rsocket/src/error.rs @@ -1,5 +1,6 @@ use std::fmt; use std::io; + use thiserror::Error; pub const ERR_INVALID_SETUP: u32 = 0x0000_0001; diff --git a/rsocket/src/extension/composite.rs b/rsocket/src/extension/composite.rs index b9df67c..239b7af 100644 --- a/rsocket/src/extension/composite.rs +++ b/rsocket/src/extension/composite.rs @@ -1,11 +1,13 @@ -use super::mime::MimeType; -use crate::error::RSocketError; -use crate::utils::{u24, Writeable}; -use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::collections::LinkedList; use std::convert::TryFrom; use std::result::Result; +use bytes::{Buf, BufMut, Bytes, BytesMut}; + +use super::mime::MimeType; +use crate::error::RSocketError; +use crate::utils::{u24, Writeable}; + const MAX_MIME_LEN: usize = 0x7F + 1; #[derive(Debug, Clone, Eq, PartialEq, Default)] diff --git a/rsocket/src/extension/routing.rs b/rsocket/src/extension/routing.rs index d273f22..1ba79db 100644 --- a/rsocket/src/extension/routing.rs +++ b/rsocket/src/extension/routing.rs @@ -1,6 +1,7 @@ +use bytes::{Buf, BufMut, Bytes, BytesMut}; + use crate::error::RSocketError; use crate::utils::Writeable; -use bytes::{Buf, BufMut, Bytes, BytesMut}; const MAX_ROUTING_TAG_LEN: usize = 0xFF; diff --git a/rsocket/src/frame/error.rs b/rsocket/src/frame/error.rs index ffbf2b1..e9a3c68 100644 --- a/rsocket/src/frame/error.rs +++ b/rsocket/src/frame/error.rs @@ -1,8 +1,10 @@ +use std::fmt; + +use bytes::{Buf, BufMut, Bytes, BytesMut}; + use super::{Body, Frame}; use crate::error::RSocketError; use crate::utils::Writeable; -use bytes::{Buf, BufMut, Bytes, BytesMut}; -use std::fmt; #[derive(Debug, PartialEq)] pub struct Error { diff --git a/rsocket/src/frame/keepalive.rs b/rsocket/src/frame/keepalive.rs index 6e0d836..82b0e77 100644 --- a/rsocket/src/frame/keepalive.rs +++ b/rsocket/src/frame/keepalive.rs @@ -1,7 +1,8 @@ +use bytes::{Buf, BufMut, Bytes, BytesMut}; + use super::{Body, Frame}; use crate::error::RSocketError; use crate::utils::Writeable; -use bytes::{Buf, BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] pub struct Keepalive { diff --git a/rsocket/src/frame/lease.rs b/rsocket/src/frame/lease.rs index 3b305a2..a75abb4 100644 --- a/rsocket/src/frame/lease.rs +++ b/rsocket/src/frame/lease.rs @@ -1,7 +1,8 @@ +use bytes::{Buf, BufMut, Bytes, BytesMut}; + use super::{Body, Frame}; use crate::error::RSocketError; use crate::utils::Writeable; -use bytes::{Buf, BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] pub struct Lease { diff --git a/rsocket/src/frame/metadata_push.rs b/rsocket/src/frame/metadata_push.rs index edd1605..6cda0f5 100644 --- a/rsocket/src/frame/metadata_push.rs +++ b/rsocket/src/frame/metadata_push.rs @@ -1,6 +1,7 @@ +use bytes::{Buf, BufMut, Bytes, BytesMut}; + use super::{Body, Frame}; use crate::utils::Writeable; -use bytes::{Buf, BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] pub struct MetadataPush { diff --git a/rsocket/src/frame/mod.rs b/rsocket/src/frame/mod.rs index 9ff368d..c61752f 100644 --- a/rsocket/src/frame/mod.rs +++ b/rsocket/src/frame/mod.rs @@ -1,6 +1,7 @@ +use bytes::{Buf, BufMut, Bytes, BytesMut}; + use crate::error::RSocketError; use crate::utils::Writeable; -use bytes::{Buf, BufMut, Bytes, BytesMut}; mod cancel; mod error; diff --git a/rsocket/src/frame/payload.rs b/rsocket/src/frame/payload.rs index c8deff7..3a06720 100644 --- a/rsocket/src/frame/payload.rs +++ b/rsocket/src/frame/payload.rs @@ -1,8 +1,9 @@ +use bytes::{BufMut, Bytes, BytesMut}; + use super::utils; use super::{Body, Frame}; use crate::utils::Writeable; use crate::Result; -use bytes::{BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] pub struct Payload { diff --git a/rsocket/src/frame/request_channel.rs b/rsocket/src/frame/request_channel.rs index f7ba6e8..9555dcf 100644 --- a/rsocket/src/frame/request_channel.rs +++ b/rsocket/src/frame/request_channel.rs @@ -1,8 +1,9 @@ +use bytes::{Buf, BufMut, Bytes, BytesMut}; + use super::utils; use super::{Body, Frame, REQUEST_MAX}; use crate::error::RSocketError; use crate::utils::Writeable; -use bytes::{Buf, BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] pub struct RequestChannel { diff --git a/rsocket/src/frame/request_fnf.rs b/rsocket/src/frame/request_fnf.rs index 80411a3..ed34e68 100644 --- a/rsocket/src/frame/request_fnf.rs +++ b/rsocket/src/frame/request_fnf.rs @@ -1,6 +1,7 @@ +use bytes::{BufMut, Bytes, BytesMut}; + use super::{utils, Body, Frame}; use crate::utils::Writeable; -use bytes::{BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] pub struct RequestFNF { diff --git a/rsocket/src/frame/request_n.rs b/rsocket/src/frame/request_n.rs index 1f6be4a..4d557e2 100644 --- a/rsocket/src/frame/request_n.rs +++ b/rsocket/src/frame/request_n.rs @@ -1,7 +1,8 @@ +use bytes::{Buf, BufMut, Bytes, BytesMut}; + use super::{utils, Body, Frame, REQUEST_MAX}; use crate::error::RSocketError; use crate::utils::Writeable; -use bytes::{Buf, BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] pub struct RequestN { diff --git a/rsocket/src/frame/request_response.rs b/rsocket/src/frame/request_response.rs index f2a21de..5f120cf 100644 --- a/rsocket/src/frame/request_response.rs +++ b/rsocket/src/frame/request_response.rs @@ -1,6 +1,7 @@ +use bytes::{BufMut, Bytes, BytesMut}; + use super::{utils, Body, Frame}; use crate::utils::Writeable; -use bytes::{BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] pub struct RequestResponse { diff --git a/rsocket/src/frame/request_stream.rs b/rsocket/src/frame/request_stream.rs index 8ff9326..254b86c 100644 --- a/rsocket/src/frame/request_stream.rs +++ b/rsocket/src/frame/request_stream.rs @@ -1,7 +1,8 @@ +use bytes::{Buf, BufMut, Bytes, BytesMut}; + use super::{utils, Body, Frame, REQUEST_MAX}; use crate::error::RSocketError; use crate::utils::Writeable; -use bytes::{Buf, BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] pub struct RequestStream { diff --git a/rsocket/src/frame/resume.rs b/rsocket/src/frame/resume.rs index 4fea1bc..934c086 100644 --- a/rsocket/src/frame/resume.rs +++ b/rsocket/src/frame/resume.rs @@ -1,7 +1,8 @@ +use bytes::{Buf, BufMut, Bytes, BytesMut}; + use super::{Body, Frame, Version}; use crate::error::RSocketError; use crate::utils::Writeable; -use bytes::{Buf, BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] pub struct Resume { diff --git a/rsocket/src/frame/resume_ok.rs b/rsocket/src/frame/resume_ok.rs index b541ff1..0e53fec 100644 --- a/rsocket/src/frame/resume_ok.rs +++ b/rsocket/src/frame/resume_ok.rs @@ -1,7 +1,8 @@ +use bytes::{Buf, BufMut, Bytes, BytesMut}; + use super::{Body, Frame}; use crate::error::RSocketError; use crate::utils::Writeable; -use bytes::{Buf, BufMut, Bytes, BytesMut}; #[derive(Debug, PartialEq)] pub struct ResumeOK { diff --git a/rsocket/src/frame/setup.rs b/rsocket/src/frame/setup.rs index 7c99531..c4f880a 100644 --- a/rsocket/src/frame/setup.rs +++ b/rsocket/src/frame/setup.rs @@ -1,9 +1,11 @@ +use std::time::Duration; + +use bytes::{Buf, BufMut, Bytes, BytesMut}; + use super::utils; use super::{Body, Frame, Version}; use crate::error::RSocketError; use crate::utils::{Writeable, DEFAULT_MIME_TYPE}; -use bytes::{Buf, BufMut, Bytes, BytesMut}; -use std::time::Duration; #[derive(Debug, PartialEq)] pub struct Setup { diff --git a/rsocket/src/frame/utils.rs b/rsocket/src/frame/utils.rs index badac2f..c12e906 100644 --- a/rsocket/src/frame/utils.rs +++ b/rsocket/src/frame/utils.rs @@ -1,7 +1,8 @@ +use bytes::{Buf, BufMut, Bytes, BytesMut}; + use super::Frame; use crate::error::RSocketError; use crate::utils::{u24, Writeable}; -use bytes::{Buf, BufMut, Bytes, BytesMut}; #[inline] pub(crate) fn read_payload( diff --git a/rsocket/src/frame/version.rs b/rsocket/src/frame/version.rs index cf2c042..8f090a5 100644 --- a/rsocket/src/frame/version.rs +++ b/rsocket/src/frame/version.rs @@ -1,6 +1,7 @@ -use crate::utils::Writeable; use bytes::{Buf, BufMut, Bytes, BytesMut}; +use crate::utils::Writeable; + #[derive(Debug, Copy, Clone, PartialEq)] pub struct Version { major: u16, diff --git a/rsocket/src/payload/normal.rs b/rsocket/src/payload/normal.rs index f0c3e03..fbd2066 100644 --- a/rsocket/src/payload/normal.rs +++ b/rsocket/src/payload/normal.rs @@ -1,6 +1,7 @@ +use bytes::Bytes; + use super::misc::bytes_to_utf8; use crate::frame; -use bytes::Bytes; #[derive(Debug, Clone)] pub struct Payload { diff --git a/rsocket/src/payload/setup.rs b/rsocket/src/payload/setup.rs index 7ce4057..8d25d92 100644 --- a/rsocket/src/payload/setup.rs +++ b/rsocket/src/payload/setup.rs @@ -1,8 +1,10 @@ +use std::time::Duration; + +use bytes::Bytes; + use super::misc::bytes_to_utf8; use crate::frame::Setup; use crate::utils::DEFAULT_MIME_TYPE; -use bytes::Bytes; -use std::time::Duration; #[derive(Debug)] pub struct SetupPayload { diff --git a/rsocket/src/prelude.rs b/rsocket/src/prelude.rs index 03cb1b8..892de4f 100644 --- a/rsocket/src/prelude.rs +++ b/rsocket/src/prelude.rs @@ -1,5 +1,6 @@ +pub use futures::{Sink, SinkExt, Stream, StreamExt}; + pub use crate::core::RSocketFactory; pub use crate::payload::{Payload, PayloadBuilder, SetupPayload, SetupPayloadBuilder}; pub use crate::spi::*; pub use crate::transport::{ServerTransport, Transport}; -pub use futures::{Sink, SinkExt, Stream, StreamExt}; diff --git a/rsocket/src/spi.rs b/rsocket/src/spi.rs index b3b0e6f..070b873 100644 --- a/rsocket/src/spi.rs +++ b/rsocket/src/spi.rs @@ -1,10 +1,12 @@ -use crate::payload::{Payload, SetupPayload}; -use crate::Result; -use async_trait::async_trait; -use futures::Stream; use std::future::Future; use std::pin::Pin; +use async_trait::async_trait; +use futures::Stream; + +use crate::payload::{Payload, SetupPayload}; +use crate::Result; + pub type ClientResponder = Box Box>; pub type ServerResponder = Box) -> Result>>; diff --git a/rsocket/src/transport/fragmentation.rs b/rsocket/src/transport/fragmentation.rs index 3388549..bf6612c 100644 --- a/rsocket/src/transport/fragmentation.rs +++ b/rsocket/src/transport/fragmentation.rs @@ -1,7 +1,9 @@ +use std::collections::LinkedList; + +use bytes::{Buf, BufMut, Bytes, BytesMut}; + use crate::frame::{self, Body, Frame}; use crate::payload::Payload; -use bytes::{Buf, BufMut, Bytes, BytesMut}; -use std::collections::LinkedList; pub(crate) const MIN_MTU: usize = 64; @@ -136,10 +138,11 @@ impl Joiner { #[cfg(test)] mod tests { + use bytes::{Buf, Bytes}; + use crate::frame::{self, Frame}; use crate::payload::Payload; use crate::transport::{Joiner, Splitter}; - use bytes::{Buf, Bytes}; #[test] fn test_joiner() { diff --git a/rsocket/src/transport/misc.rs b/rsocket/src/transport/misc.rs index 7b67b66..f99806c 100644 --- a/rsocket/src/transport/misc.rs +++ b/rsocket/src/transport/misc.rs @@ -1,7 +1,8 @@ -use crate::frame::Frame; use std::sync::atomic::{AtomicI64, AtomicU32, Ordering}; use std::sync::Arc; +use crate::frame::Frame; + #[derive(Debug, Clone)] pub(crate) struct StreamID { inner: Arc, diff --git a/rsocket/src/transport/socket.rs b/rsocket/src/transport/socket.rs index 6f1d99b..4cbb302 100644 --- a/rsocket/src/transport/socket.rs +++ b/rsocket/src/transport/socket.rs @@ -1,3 +1,14 @@ +use std::future::Future; +use std::pin::Pin; +use std::sync::Arc; + +use async_stream::stream; +use async_trait::async_trait; +use bytes::{Buf, BufMut, Bytes, BytesMut}; +use dashmap::{mapref::entry::Entry, DashMap}; +use futures::{Sink, SinkExt, Stream, StreamExt}; +use tokio::sync::{mpsc, oneshot, RwLock}; + use super::fragmentation::{Joiner, Splitter}; use super::misc::{debug_frame, Counter, StreamID}; use super::spi::*; @@ -7,15 +18,6 @@ use crate::payload::{Payload, SetupPayload}; use crate::spi::{Flux, RSocket, ServerResponder}; use crate::utils::EmptyRSocket; use crate::{runtime, Result}; -use async_stream::stream; -use async_trait::async_trait; -use bytes::{Buf, BufMut, Bytes, BytesMut}; -use dashmap::{mapref::entry::Entry, DashMap}; -use futures::{Sink, SinkExt, Stream, StreamExt}; -use std::future::Future; -use std::pin::Pin; -use std::sync::Arc; -use tokio::sync::{mpsc, oneshot, RwLock}; #[derive(Clone)] pub(crate) struct DuplexSocket { diff --git a/rsocket/src/utils.rs b/rsocket/src/utils.rs index b5d4b64..4b6d2c8 100644 --- a/rsocket/src/utils.rs +++ b/rsocket/src/utils.rs @@ -1,17 +1,19 @@ -use super::spi::{Flux, RSocket}; -use crate::error::RSocketError; -use crate::payload::Payload; -use crate::runtime; -use crate::Result; +use std::error::Error; +use std::future::Future; +use std::pin::Pin; + use async_stream::stream; use async_trait::async_trait; use bytes::{Buf, BufMut, Bytes, BytesMut}; use futures::{pin_mut, FutureExt, Sink, SinkExt, Stream, StreamExt}; -use std::error::Error; -use std::future::Future; -use std::pin::Pin; use tokio::sync::mpsc; +use super::spi::{Flux, RSocket}; +use crate::error::RSocketError; +use crate::payload::Payload; +use crate::runtime; +use crate::Result; + pub const DEFAULT_MIME_TYPE: &str = "application/binary"; pub struct EchoRSocket; diff --git a/rustfmt.toml b/rustfmt.toml index 32a9786..a75a838 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1 +1,3 @@ edition = "2018" +group_imports="StdExternalCrate" + From d62b636ebbe3c9317f026fe8853f37c435191eea Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Wed, 13 Jan 2021 23:25:33 +0800 Subject: [PATCH 46/70] feat: close connection correctly when client is dropped (#40) --- rsocket/src/core/client.rs | 53 ++++++++++++++++++++++++++------------ rsocket/src/core/server.rs | 6 ++--- 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/rsocket/src/core/client.rs b/rsocket/src/core/client.rs index 810502a..65157ef 100644 --- a/rsocket/src/core/client.rs +++ b/rsocket/src/core/client.rs @@ -22,6 +22,7 @@ use crate::Result; pub struct Client { closed: Arc, socket: DuplexSocket, + closing: mpsc::Sender<()>, } pub struct ClientBuilder { @@ -171,28 +172,41 @@ where // begin read loop let closer = self.closer.take(); - let closed = Arc::new(Notify::new()); - let closed_clone = closed.clone(); + let close_notify = Arc::new(Notify::new()); + let close_notify_clone = close_notify.clone(); + let (closing, mut closing_rx) = mpsc::channel::<()>(1); let (read_tx, mut read_rx) = mpsc::unbounded_channel::(); + // read frames from stream, then writes into channel runtime::spawn(async move { - while let Some(next) = stream.next().await { - match next { - Ok(frame) => { - if let Err(e) = read_tx.send(frame) { - error!("read next frame failed: {}", e); - break; + loop { + tokio::select! { + res = stream.next() => { + match res { + Some(next) => match next { + Ok(frame) => { + if let Err(e) = read_tx.send(frame) { + error!("forward frame failed: {}", e); + break; + } + } + Err(e) => { + error!("read frame failed: {}", e); + break; + } + } + None => break, } } - Err(e) => { - error!("read next frame failed: {}", e); - break; + _ = closing_rx.recv() => { + break } } } }); + // process frames runtime::spawn(async move { while let Some(next) = read_rx.recv().await { if let Err(e) = cloned_socket.dispatch(next, None).await { @@ -205,12 +219,12 @@ where let close_frame = frame::Error::builder(0, 0) .set_code(ERR_CONN_CLOSED) .build(); - if let Err(_) = cloned_snd_tx.send(close_frame) { - debug!("send close notify frame failed!"); + if let Err(e) = cloned_snd_tx.send(close_frame) { + debug!("send close notify frame failed: {}", e); } // notify client closed - closed_clone.notify_one(); + close_notify_clone.notify_one(); // invoke on_close handler if let Some(mut invoke) = closer { @@ -219,13 +233,18 @@ where }); socket.setup(setup).await; - Ok(Client::new(socket, closed)) + + Ok(Client::new(socket, close_notify, closing)) } } impl Client { - fn new(socket: DuplexSocket, closed: Arc) -> Client { - Client { socket, closed } + fn new(socket: DuplexSocket, closed: Arc, closing: mpsc::Sender<()>) -> Client { + Client { + socket, + closed, + closing, + } } pub async fn wait_for_close(self) { diff --git a/rsocket/src/core/server.rs b/rsocket/src/core/server.rs index deb4dfb..3b39fb5 100644 --- a/rsocket/src/core/server.rs +++ b/rsocket/src/core/server.rs @@ -133,12 +133,12 @@ where match reader.next().await { Some(Ok(frame)) => { if let Err(e) = read_tx.send(frame) { - error!("read next frame failed: {}", e); + error!("forward frame failed: {}", e); break; } } Some(Err(e)) => { - error!("read next frame failed: {}", e); + error!("read frame failed: {}", e); break; } None => { @@ -150,7 +150,7 @@ where while let Some(frame) = read_rx.recv().await { if let Err(e) = socket.dispatch(frame, acceptor.as_ref().as_ref()).await { - error!("dispatch incoming frame failed: {}", e); + error!("dispatch frame failed: {}", e); break; } } From 6a101e27bd3c319cbe194ba71f40f03a94a1e21f Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Thu, 14 Jan 2021 22:43:40 +0800 Subject: [PATCH 47/70] chore: config chglog (#41) --- .chglog/CHANGELOG.tpl.md | 30 +++++++++++ .chglog/config.yml | 28 ++++++++++ CHANGELOG.md | 111 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100755 .chglog/CHANGELOG.tpl.md create mode 100755 .chglog/config.yml create mode 100644 CHANGELOG.md diff --git a/.chglog/CHANGELOG.tpl.md b/.chglog/CHANGELOG.tpl.md new file mode 100755 index 0000000..63ce69b --- /dev/null +++ b/.chglog/CHANGELOG.tpl.md @@ -0,0 +1,30 @@ +{{ range .Versions }} + +## {{ if .Tag.Previous }}[{{ .Tag.Name }}]({{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }}){{ else }}{{ .Tag.Name }}{{ end }} ({{ datetime "2006-01-02" .Tag.Date }}) + +{{ range .CommitGroups -}} +### {{ .Title }} + +{{ range .Commits -}} +* {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }} +{{ end }} +{{ end -}} + +{{- if .MergeCommits -}} +### Pull Requests + +{{ range .MergeCommits -}} +* {{ .Header }} +{{ end }} +{{ end -}} + +{{- if .NoteGroups -}} +{{ range .NoteGroups -}} +### {{ .Title }} + +{{ range .Notes }} +{{ .Body }} +{{ end }} +{{ end -}} +{{ end -}} +{{ end -}} \ No newline at end of file diff --git a/.chglog/config.yml b/.chglog/config.yml new file mode 100755 index 0000000..dc64da1 --- /dev/null +++ b/.chglog/config.yml @@ -0,0 +1,28 @@ +style: github +template: CHANGELOG.tpl.md +info: + title: CHANGELOG + repository_url: https://github.com/rsocket/rsocket-rust +options: + commits: + # filters: + # Type: + # - feat + # - fix + # - perf + # - refactor + commit_groups: + # title_maps: + # feat: Features + # fix: Bug Fixes + # perf: Performance Improvements + # refactor: Code Refactoring + header: + pattern: "^(\\w*)(?:\\(([\\w\\$\\.\\-\\*\\s]*)\\))?\\:\\s(.*)$" + pattern_maps: + - Type + - Scope + - Subject + notes: + keywords: + - BREAKING CHANGE \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..2f8c68a --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,111 @@ + + +## [v0.6.0](https://github.com/rsocket/rsocket-rust/compare/v0.5.3...v0.6.0) (2020-12-13) + +### Chore + +* prelease 0.6 +* upgrade deps +* use gh actions instead of travis ([#22](https://github.com/rsocket/rsocket-rust/issues/22)) + +### Feat + +* implement client-side keepalive ([#25](https://github.com/rsocket/rsocket-rust/issues/25)) +* support tokio v0.3.x ([#23](https://github.com/rsocket/rsocket-rust/issues/23)) + +### Fix + +* convert bytes to utf8 safely ([#27](https://github.com/rsocket/rsocket-rust/issues/27)) +* optimize bytes write action ([#24](https://github.com/rsocket/rsocket-rust/issues/24)) + +### Refactor + +* use thiserror & anyhow as error struct ([#20](https://github.com/rsocket/rsocket-rust/issues/20)) + +### Pull Requests + +* Merge pull request [#19](https://github.com/rsocket/rsocket-rust/issues/19) from rsocket/develop + + + +## [v0.5.3](https://github.com/rsocket/rsocket-rust/compare/v0.5.2...v0.5.3) (2020-06-11) + +### Pull Requests + +* Merge pull request [#17](https://github.com/rsocket/rsocket-rust/issues/17) from rsocket/develop +* Merge pull request [#16](https://github.com/rsocket/rsocket-rust/issues/16) from seal90/develop + + + +## [v0.5.2](https://github.com/rsocket/rsocket-rust/compare/v0.5.1...v0.5.2) (2020-05-26) + +### Pull Requests + +* Merge pull request [#14](https://github.com/rsocket/rsocket-rust/issues/14) from rsocket/feature/messaging +* Merge pull request [#11](https://github.com/rsocket/rsocket-rust/issues/11) from kuronyago/feature/wasm_fire_and_forget +* Merge pull request [#9](https://github.com/rsocket/rsocket-rust/issues/9) from kuronyago/docs/readme_for_websocket_example + + + +## [v0.5.1](https://github.com/rsocket/rsocket-rust/compare/v0.5.0...v0.5.1) (2020-04-06) + +### Pull Requests + +* Merge pull request [#8](https://github.com/rsocket/rsocket-rust/issues/8) from rsocket/develop + + + +## [v0.5.0](https://github.com/rsocket/rsocket-rust/compare/v0.4.0...v0.5.0) (2020-02-22) + +### Pull Requests + +* Merge pull request [#6](https://github.com/rsocket/rsocket-rust/issues/6) from rsocket/improve/pick_transport + + + +## [v0.4.0](https://github.com/rsocket/rsocket-rust/compare/v0.3.0...v0.4.0) (2019-12-24) + +### Bugfix + +* response payload of REQUEST_RESPONSE will be sent with NEXT|COMPLETE flag. + +### Pull Requests + +* Merge pull request [#4](https://github.com/rsocket/rsocket-rust/issues/4) from rsocket/develop + + + +## [v0.3.0](https://github.com/rsocket/rsocket-rust/compare/v0.2.0...v0.3.0) (2019-12-04) + +### Pull Requests + +* Merge pull request [#3](https://github.com/rsocket/rsocket-rust/issues/3) from rsocket/feature/routing_metadata + + + +## [v0.2.0](https://github.com/rsocket/rsocket-rust/compare/v0.1.5...v0.2.0) (2019-11-29) + +### Pull Requests + +* Merge pull request [#2](https://github.com/rsocket/rsocket-rust/issues/2) from rsocket/feature/async_await + + + +## [v0.1.5](https://github.com/rsocket/rsocket-rust/compare/v0.1.4...v0.1.5) (2019-10-08) + + + +## [v0.1.4](https://github.com/rsocket/rsocket-rust/compare/v0.1.3...v0.1.4) (2019-09-06) + + + +## [v0.1.3](https://github.com/rsocket/rsocket-rust/compare/v0.1.2...v0.1.3) (2019-09-03) + + + +## [v0.1.2](https://github.com/rsocket/rsocket-rust/compare/v0.1.0...v0.1.2) (2019-09-02) + + + +## v0.1.0 (2019-08-29) + From 3c555e727db8bb08077886b8bb84d34639698115 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Thu, 14 Jan 2021 23:03:49 +0800 Subject: [PATCH 48/70] chore: update deps (#42) --- examples/Cargo.toml | 2 +- rsocket-messaging/Cargo.toml | 2 +- rsocket-test/Cargo.toml | 4 ++-- rsocket-transport-tcp/Cargo.toml | 4 ++-- rsocket-transport-wasm/Cargo.toml | 4 ++-- rsocket-transport-websocket/Cargo.toml | 2 +- rsocket/Cargo.toml | 6 +++--- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index ca4377e..f564ddd 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -8,7 +8,7 @@ publish = false [dev-dependencies] log = "0.4.13" env_logger = "0.8.2" -futures = "0.3.9" +futures = "0.3.10" clap = "2.33.3" [dev-dependencies.rsocket_rust] diff --git a/rsocket-messaging/Cargo.toml b/rsocket-messaging/Cargo.toml index ed6cabd..e8f25d7 100644 --- a/rsocket-messaging/Cargo.toml +++ b/rsocket-messaging/Cargo.toml @@ -10,7 +10,7 @@ homepage = "https://github.com/rsocket/rsocket-rust" description = "Communicate with Spring RSocket Messaging." [dependencies] -futures = "0.3.9" +futures = "0.3.10" bytes = "1.0.1" serde = "1.0.119" serde_json = "1.0.61" diff --git a/rsocket-test/Cargo.toml b/rsocket-test/Cargo.toml index 0da251b..3474fb4 100644 --- a/rsocket-test/Cargo.toml +++ b/rsocket-test/Cargo.toml @@ -7,11 +7,11 @@ publish = false [dev-dependencies] log = "0.4" -futures = "0.3.9" +futures = "0.3.10" env_logger = "0.8.2" bytes = "1.0.1" hex = "0.4.2" -rand = "0.8.1" +rand = "0.8.2" serde = "1.0.119" serde_derive = "1.0.119" diff --git a/rsocket-transport-tcp/Cargo.toml b/rsocket-transport-tcp/Cargo.toml index d85b109..c6dccb1 100644 --- a/rsocket-transport-tcp/Cargo.toml +++ b/rsocket-transport-tcp/Cargo.toml @@ -15,7 +15,7 @@ tls = ["tokio-native-tls"] [dependencies] log = "0.4.13" -futures = "0.3.9" +futures = "0.3.10" bytes = "1.0.1" [dependencies.rsocket_rust] @@ -28,7 +28,7 @@ default-features = false features = [ "rt", "rt-multi-thread", "net", "sync", "io-util", "macros" ] [dependencies.tokio-util] -version = "0.6.0" +version = "0.6.1" default-features = false features = ["codec"] diff --git a/rsocket-transport-wasm/Cargo.toml b/rsocket-transport-wasm/Cargo.toml index 59d6f3b..67087bc 100644 --- a/rsocket-transport-wasm/Cargo.toml +++ b/rsocket-transport-wasm/Cargo.toml @@ -12,8 +12,8 @@ description = "WASM Websocket RSocket transport implementation." [dependencies] bytes = "1.0.1" wasm-bindgen-futures = "0.4.19" -futures-channel = "0.3.9" -futures-util = "0.3.9" +futures-channel = "0.3.10" +futures-util = "0.3.10" js-sys = "0.3.46" serde = "1.0.119" serde_derive = "1.0.119" diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index 2df740d..06affa0 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -11,7 +11,7 @@ description = "Websocket RSocket transport implementation." [dependencies] log = "0.4.13" -futures = "0.3.9" +futures = "0.3.10" bytes = "1.0.1" url = "2.2.0" tokio-tungstenite = "0.13.0" diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index 775f7d1..bfc126a 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -12,10 +12,10 @@ description = "rsocket-rust is an implementation of the RSocket protocol in Rust [dependencies] log = "0.4.13" bytes = "1.0.1" -futures = "0.3.9" +futures = "0.3.10" lazy_static = "1.4.0" async-trait = "0.1.42" -dashmap = "4.0.1" +dashmap = "4.0.2" thiserror = "1.0.23" anyhow = "1.0.38" async-stream = "0.3.0" @@ -26,7 +26,7 @@ wasm-bindgen-futures = "0.4.19" [dependencies.tokio] version = "1.0.1" default-features = false -features = [ "rt", "rt-multi-thread", "sync", "time" ] +features = [ "macros", "rt", "rt-multi-thread", "sync", "time" ] [features] default = [] From 413f6b3cf845590c0469abbcbefa256494031e87 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Thu, 14 Jan 2021 23:22:50 +0800 Subject: [PATCH 49/70] chore: upgrade version to 0.7.1 --- CHANGELOG.md | 29 ++++++++++++++++++++++++++ rsocket-messaging/Cargo.toml | 2 +- rsocket-transport-tcp/Cargo.toml | 2 +- rsocket-transport-wasm/Cargo.toml | 2 +- rsocket-transport-websocket/Cargo.toml | 2 +- rsocket/Cargo.toml | 2 +- 6 files changed, 34 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f8c68a..07213a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,33 @@ + +## [v0.7.0](https://github.com/rsocket/rsocket-rust/compare/v0.6.0...v0.7.0) (2021-01-14) + +### Chore + +* update deps ([#42](https://github.com/rsocket/rsocket-rust/issues/42)) +* config chglog ([#41](https://github.com/rsocket/rsocket-rust/issues/41)) +* use mkcert to generate TLS example certificates and keys ([#38](https://github.com/rsocket/rsocket-rust/issues/38)) +* add RSocket trait example in readme +* fix readme +* bump tokio to v0.3.6 +* **rustfmt:** optimize import ([#39](https://github.com/rsocket/rsocket-rust/issues/39)) + +### Feat + +* close connection correctly when client is dropped ([#40](https://github.com/rsocket/rsocket-rust/issues/40)) +* migrate to tokio v1 +* change transport api ([#35](https://github.com/rsocket/rsocket-rust/issues/35)) +* implment tls transport ([#31](https://github.com/rsocket/rsocket-rust/issues/31)) +* redesign RSocket trait based on async_trait +* **request_response:** handle empty response correctly + +### Fix + +* register client-side responder correctly ([#36](https://github.com/rsocket/rsocket-rust/issues/36)) +* simplify Option convert +* remove useless examples + + ## [v0.6.0](https://github.com/rsocket/rsocket-rust/compare/v0.5.3...v0.6.0) (2020-12-13) diff --git a/rsocket-messaging/Cargo.toml b/rsocket-messaging/Cargo.toml index e8f25d7..c464f8a 100644 --- a/rsocket-messaging/Cargo.toml +++ b/rsocket-messaging/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_messaging" -version = "0.7.0" +version = "0.7.1" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" diff --git a/rsocket-transport-tcp/Cargo.toml b/rsocket-transport-tcp/Cargo.toml index c6dccb1..0c2c353 100644 --- a/rsocket-transport-tcp/Cargo.toml +++ b/rsocket-transport-tcp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_tcp" -version = "0.7.0" +version = "0.7.1" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" diff --git a/rsocket-transport-wasm/Cargo.toml b/rsocket-transport-wasm/Cargo.toml index 67087bc..e9688b3 100644 --- a/rsocket-transport-wasm/Cargo.toml +++ b/rsocket-transport-wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_wasm" -version = "0.7.0" +version = "0.7.1" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index 06affa0..40de709 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_websocket" -version = "0.7.0" +version = "0.7.1" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index bfc126a..9d5fd4d 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust" -version = "0.7.0" +version = "0.7.1" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" From 8dddb71f87112bcfdd7b3161b2a51a4cd0e3575a Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Sun, 17 Jan 2021 15:54:26 +0800 Subject: [PATCH 50/70] chore(readme): update examples --- README.md | 9 +++--- rsocket/README.md | 74 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 76 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 886afcf..9242242 100644 --- a/README.md +++ b/README.md @@ -42,12 +42,12 @@ async fn main() -> Result<()> { RSocketFactory::receive() .transport(TcpServerTransport::from("127.0.0.1:7878")) .acceptor(Box::new(|setup, _socket| { - info!("accept setup: {:?}", setup); + println!("accept setup: {:?}", setup); Ok(Box::new(EchoRSocket)) // Or you can reject setup // Err(From::from("SETUP_NOT_ALLOW")) })) - .on_start(|| info!("+++++++ echo server started! +++++++")) + .on_start(Box::new(|| println!("+++++++ echo server started! +++++++"))) .serve() .await } @@ -66,6 +66,7 @@ async fn main() -> Result<()> { .transport(TcpClientTransport::from("127.0.0.1:7878")) .setup(Payload::from("READY!")) .mime_type("text/plain", "text/plain") + .on_close(Box::new(|| println!("connection closed"))) .start() .await?; let req = Payload::builder() @@ -80,7 +81,6 @@ async fn main() -> Result<()> { Ok(()) } - ``` ### Implement RSocket trait @@ -90,11 +90,12 @@ Example for access Redis([crates](https://crates.io/crates/redis)): > NOTICE: add dependency in Cargo.toml => redis = { version = "0.19.0", features = [ "aio" ] } ```rust +use std::str::FromStr; + use redis::Client as RedisClient; use rsocket_rust::async_trait; use rsocket_rust::prelude::*; use rsocket_rust::Result; -use std::str::FromStr; #[derive(Clone)] pub struct RedisDao { diff --git a/rsocket/README.md b/rsocket/README.md index ebed0d0..76cda74 100644 --- a/rsocket/README.md +++ b/rsocket/README.md @@ -32,12 +32,11 @@ async fn main() -> Result<()> { .transport(TcpServerTransport::from("127.0.0.1:7878")) .acceptor(Box::new(|setup, _socket| { println!("accept setup: {:?}", setup); - // Use EchoRSocket as example RSocket, you can implement RSocket trait. Ok(Box::new(EchoRSocket)) // Or you can reject setup // Err(From::from("SETUP_NOT_ALLOW")) })) - .on_start(|| println!("+++++++ echo server started! +++++++")) + .on_start(Box::new(|| println!("+++++++ echo server started! +++++++"))) .serve() .await } @@ -56,6 +55,7 @@ async fn main() -> Result<()> { .transport(TcpClientTransport::from("127.0.0.1:7878")) .setup(Payload::from("READY!")) .mime_type("text/plain", "text/plain") + .on_close(Box::new(|| println!("connection closed"))) .start() .await?; let req = Payload::builder() @@ -64,8 +64,76 @@ async fn main() -> Result<()> { .build(); let res = cli.request_response(req).await?; println!("got: {:?}", res); - cli.close(); + + // If you want to block until socket disconnected. + cli.wait_for_close().await; + Ok(()) } +``` + +### Implement RSocket trait + +Example for access Redis([crates](https://crates.io/crates/redis)): + +> NOTICE: add dependency in Cargo.toml => redis = { version = "0.19.0", features = [ "aio" ] } + +```rust +use std::str::FromStr; + +use redis::Client as RedisClient; +use rsocket_rust::async_trait; +use rsocket_rust::prelude::*; +use rsocket_rust::Result; + +#[derive(Clone)] +pub struct RedisDao { + inner: RedisClient, +} + +// Create RedisDao from str. +// Example: RedisDao::from_str("redis://127.0.0.1").expect("Connect redis failed!"); +impl FromStr for RedisDao { + type Err = redis::RedisError; + + fn from_str(s: &str) -> std::result::Result { + let client = redis::Client::open(s)?; + Ok(RedisDao { inner: client }) + } +} + +#[async_trait] +impl RSocket for RedisDao { + async fn request_response(&self, req: Payload) -> Result> { + let client = self.inner.clone(); + let mut conn = client.get_async_connection().await?; + let value: redis::RedisResult> = redis::cmd("GET") + .arg(&[req.data_utf8()]) + .query_async(&mut conn) + .await; + match value { + Ok(Some(value)) => Ok(Some(Payload::builder().set_data_utf8(&value).build())), + Ok(None) => Ok(None), + Err(e) => Err(e.into()), + } + } + + async fn metadata_push(&self, _req: Payload) -> Result<()> { + todo!() + } + + async fn fire_and_forget(&self, _req: Payload) -> Result<()> { + todo!() + } + + fn request_stream(&self, _req: Payload) -> Flux> { + todo!() + } + + fn request_channel(&self, _reqs: Flux>) -> Flux> { + todo!() + } +} ``` + From e702ae63e84b0f9664c257309ec7fcfc84c0fc96 Mon Sep 17 00:00:00 2001 From: Jeff Tsai Date: Wed, 24 Feb 2021 15:52:39 +0800 Subject: [PATCH 51/70] feat: use cfg_if and once_cell --- rsocket-transport-tcp/Cargo.toml | 9 +++--- rsocket-transport-tcp/src/client/mod.rs | 11 ++++--- rsocket-transport-tcp/src/connection/mod.rs | 11 ++++--- rsocket-transport-tcp/src/lib.rs | 19 +++++++----- rsocket-transport-tcp/src/server/mod.rs | 12 ++++---- rsocket-transport-wasm/Cargo.toml | 18 +++++------ rsocket-transport-websocket/Cargo.toml | 8 ++--- rsocket/Cargo.toml | 5 ++-- rsocket/src/extension/mime.rs | 33 +++++++++++---------- rsocket/src/lib.rs | 14 +++++---- rsocket/src/runtime/mod.rs | 16 +++++----- 11 files changed, 86 insertions(+), 70 deletions(-) diff --git a/rsocket-transport-tcp/Cargo.toml b/rsocket-transport-tcp/Cargo.toml index 0c2c353..4e166b4 100644 --- a/rsocket-transport-tcp/Cargo.toml +++ b/rsocket-transport-tcp/Cargo.toml @@ -14,21 +14,22 @@ default = [] tls = ["tokio-native-tls"] [dependencies] -log = "0.4.13" -futures = "0.3.10" +log = "0.4.14" +futures = "0.3.13" bytes = "1.0.1" +cfg-if = "1" [dependencies.rsocket_rust] path = "../rsocket" features = ["frame"] [dependencies.tokio] -version = "1.0.1" +version = "1.0.3" default-features = false features = [ "rt", "rt-multi-thread", "net", "sync", "io-util", "macros" ] [dependencies.tokio-util] -version = "0.6.1" +version = "0.6.3" default-features = false features = ["codec"] diff --git a/rsocket-transport-tcp/src/client/mod.rs b/rsocket-transport-tcp/src/client/mod.rs index f0f1acd..6cfe376 100644 --- a/rsocket-transport-tcp/src/client/mod.rs +++ b/rsocket-transport-tcp/src/client/mod.rs @@ -1,9 +1,12 @@ mod tcp; -#[cfg(feature = "tls")] -mod tls; mod uds; pub use tcp::TcpClientTransport; -#[cfg(feature = "tls")] -pub use tls::TlsClientTransport; pub use uds::UnixClientTransport; + +cfg_if! { + if #[cfg(feature = "tls")] { + mod tls; + pub use tls::TlsClientTransport; + } +} diff --git a/rsocket-transport-tcp/src/connection/mod.rs b/rsocket-transport-tcp/src/connection/mod.rs index 8df67b6..94378ad 100644 --- a/rsocket-transport-tcp/src/connection/mod.rs +++ b/rsocket-transport-tcp/src/connection/mod.rs @@ -1,10 +1,13 @@ mod codec; mod tcp; -#[cfg(feature = "tls")] -mod tls; mod uds; pub use tcp::TcpConnection; -#[cfg(feature = "tls")] -pub use tls::TlsConnection; pub use uds::UnixConnection; + +cfg_if! { + if #[cfg(feature = "tls")] { + mod tls; + pub use tls::TlsConnection; + } +} diff --git a/rsocket-transport-tcp/src/lib.rs b/rsocket-transport-tcp/src/lib.rs index dcb4f19..90f63e8 100644 --- a/rsocket-transport-tcp/src/lib.rs +++ b/rsocket-transport-tcp/src/lib.rs @@ -2,20 +2,23 @@ #[macro_use] extern crate log; +#[macro_use] +extern crate cfg_if; mod client; mod connection; mod misc; mod server; -#[cfg(feature = "tls")] -pub use client::TlsClientTransport; pub use client::{TcpClientTransport, UnixClientTransport}; -#[cfg(feature = "tls")] -pub use connection::TlsConnection; pub use connection::{TcpConnection, UnixConnection}; -#[cfg(feature = "tls")] -pub use server::TlsServerTransport; pub use server::{TcpServerTransport, UnixServerTransport}; -#[cfg(feature = "tls")] -pub use tokio_native_tls; + +cfg_if! { + if #[cfg(feature = "tls")] { + pub use tokio_native_tls; + pub use client::TlsClientTransport; + pub use connection::TlsConnection; + pub use server::TlsServerTransport; + } +} diff --git a/rsocket-transport-tcp/src/server/mod.rs b/rsocket-transport-tcp/src/server/mod.rs index 1dda335..ce1557d 100644 --- a/rsocket-transport-tcp/src/server/mod.rs +++ b/rsocket-transport-tcp/src/server/mod.rs @@ -1,10 +1,12 @@ mod tcp; - -#[cfg(feature = "tls")] -mod tls; mod uds; pub use tcp::TcpServerTransport; -#[cfg(feature = "tls")] -pub use tls::TlsServerTransport; pub use uds::UnixServerTransport; + +cfg_if! { + if #[cfg(feature = "tls")] { + mod tls; + pub use tls::TlsServerTransport; + } +} diff --git a/rsocket-transport-wasm/Cargo.toml b/rsocket-transport-wasm/Cargo.toml index e9688b3..5435a24 100644 --- a/rsocket-transport-wasm/Cargo.toml +++ b/rsocket-transport-wasm/Cargo.toml @@ -11,25 +11,25 @@ description = "WASM Websocket RSocket transport implementation." [dependencies] bytes = "1.0.1" -wasm-bindgen-futures = "0.4.19" -futures-channel = "0.3.10" -futures-util = "0.3.10" -js-sys = "0.3.46" -serde = "1.0.119" -serde_derive = "1.0.119" +wasm-bindgen-futures = "0.4.20" +futures-channel = "0.3.13" +futures-util = "0.3.13" +js-sys = "0.3.47" +serde = "1.0.123" +serde_derive = "1.0.123" async-trait = "0.1.42" -log = "0.4.13" +log = "0.4.14" [dependencies.rsocket_rust] path = "../rsocket" features = ["frame"] [dependencies.wasm-bindgen] -version = "0.2.69" +version = "0.2.70" features = ["serde-serialize"] [dependencies.web-sys] -version = "0.3.46" +version = "0.3.47" features = [ "FileReader", "ProgressEvent", diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index 40de709..4e8f7fe 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -10,10 +10,10 @@ homepage = "https://github.com/rsocket/rsocket-rust" description = "Websocket RSocket transport implementation." [dependencies] -log = "0.4.13" -futures = "0.3.10" +log = "0.4.14" +futures = "0.3.13" bytes = "1.0.1" -url = "2.2.0" +url = "2.2.1" tokio-tungstenite = "0.13.0" [dependencies.rsocket_rust] @@ -21,6 +21,6 @@ path = "../rsocket" features = ["frame"] [dependencies.tokio] -version = "1.0.1" +version = "1.0.3" default-features = false features = [ "rt", "rt-multi-thread", "net", "sync"] diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index 9d5fd4d..3538acb 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -13,18 +13,19 @@ description = "rsocket-rust is an implementation of the RSocket protocol in Rust log = "0.4.13" bytes = "1.0.1" futures = "0.3.10" -lazy_static = "1.4.0" +once_cell = "1.6.0" async-trait = "0.1.42" dashmap = "4.0.2" thiserror = "1.0.23" anyhow = "1.0.38" async-stream = "0.3.0" +cfg-if = "1" [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen-futures = "0.4.19" [dependencies.tokio] -version = "1.0.1" +version = "1.0.3" default-features = false features = [ "macros", "rt", "rt-multi-thread", "sync", "time" ] diff --git a/rsocket/src/extension/mime.rs b/rsocket/src/extension/mime.rs index e408785..8138b95 100644 --- a/rsocket/src/extension/mime.rs +++ b/rsocket/src/extension/mime.rs @@ -1,28 +1,29 @@ use std::collections::HashMap; use std::fmt; +use once_cell::sync::Lazy; + #[derive(PartialEq, Eq, Debug, Clone, Hash)] pub enum MimeType { Normal(String), WellKnown(u8), } -lazy_static! { - static ref U8_TO_STR: HashMap = { - let mut m = HashMap::new(); - for it in list_all().iter() { - m.insert(it.0, it.1); - } - m - }; - static ref STR_TO_U8: HashMap<&'static str, u8> = { - let mut m = HashMap::new(); - for it in list_all().iter() { - m.insert(it.1, it.0); - } - m - }; -} +static U8_TO_STR: Lazy> = Lazy::new(|| { + let mut m = HashMap::new(); + for it in list_all().iter() { + m.insert(it.0, it.1); + } + m +}); + +static STR_TO_U8: Lazy> = Lazy::new(|| { + let mut m = HashMap::new(); + for it in list_all().iter() { + m.insert(it.1, it.0); + } + m +}); impl MimeType { pub fn parse(value: u8) -> Option { diff --git a/rsocket/src/lib.rs b/rsocket/src/lib.rs index 073d267..25e5406 100644 --- a/rsocket/src/lib.rs +++ b/rsocket/src/lib.rs @@ -95,21 +95,25 @@ pub use async_stream::stream; /// A re-export of [`async-trait`](https://docs.rs/async-trait) for use with RSocket trait implementation. pub use async_trait::async_trait; +use cfg_if::cfg_if; #[macro_use] extern crate anyhow; #[macro_use] extern crate log; #[macro_use] -extern crate lazy_static; +extern crate cfg_if; pub mod error; pub mod extension; -#[cfg(feature = "frame")] -pub mod frame; -#[cfg(not(feature = "frame"))] -mod frame; +cfg_if! { + if #[cfg(feature = "frame")]{ + pub mod frame; + }else{ + mod frame; + } +} mod core; mod payload; diff --git a/rsocket/src/runtime/mod.rs b/rsocket/src/runtime/mod.rs index c6e150a..994d0e2 100644 --- a/rsocket/src/runtime/mod.rs +++ b/rsocket/src/runtime/mod.rs @@ -4,14 +4,12 @@ pub fn spawn(task: F) where F: Send + Future + 'static, { - #[cfg(not(target_arch = "wasm32"))] - { - tokio::spawn(task); - } - - #[cfg(target_arch = "wasm32")] - { - use wasm_bindgen_futures::spawn_local; - spawn_local(task); + cfg_if! { + if #[cfg(not(target_arch = "wasm32"))] { + tokio::spawn(task); + } else { + use wasm_bindgen_futures::spawn_local; + spawn_local(task); + } } } From 49acec609afd54187c1ff373b16f83f84d435522 Mon Sep 17 00:00:00 2001 From: Jeff Tsai Date: Wed, 24 Feb 2021 18:01:59 +0800 Subject: [PATCH 52/70] feat: add some macros --- rsocket/src/lib.rs | 13 ++++++++----- rsocket/src/macros/composite.rs | 33 +++++++++++++++++++++++++++++++++ rsocket/src/macros/mod.rs | 4 ++++ rsocket/src/macros/routing.rs | 25 +++++++++++++++++++++++++ rustfmt.toml | 1 - 5 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 rsocket/src/macros/composite.rs create mode 100644 rsocket/src/macros/mod.rs create mode 100644 rsocket/src/macros/routing.rs diff --git a/rsocket/src/lib.rs b/rsocket/src/lib.rs index 25e5406..c68a49c 100644 --- a/rsocket/src/lib.rs +++ b/rsocket/src/lib.rs @@ -95,7 +95,6 @@ pub use async_stream::stream; /// A re-export of [`async-trait`](https://docs.rs/async-trait) for use with RSocket trait implementation. pub use async_trait::async_trait; -use cfg_if::cfg_if; #[macro_use] extern crate anyhow; @@ -104,8 +103,16 @@ extern crate log; #[macro_use] extern crate cfg_if; +#[macro_use] +#[doc(hidden)] +pub mod macros; + pub mod error; pub mod extension; +pub mod prelude; +pub mod runtime; +pub mod transport; +pub mod utils; cfg_if! { if #[cfg(feature = "frame")]{ @@ -117,11 +124,7 @@ cfg_if! { mod core; mod payload; -pub mod prelude; -pub mod runtime; mod spi; -pub mod transport; -pub mod utils; pub type Error = Box; pub type Result = anyhow::Result; diff --git a/rsocket/src/macros/composite.rs b/rsocket/src/macros/composite.rs new file mode 100644 index 0000000..38fdca3 --- /dev/null +++ b/rsocket/src/macros/composite.rs @@ -0,0 +1,33 @@ +#[macro_export] +macro_rules! composite { + ($($x:expr,$y:expr),+) => { + { + let mut b = $crate::extension::CompositeMetadata::builder(); + $( + b = b.push($x.into(),$y); + )* + b.build() + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_composite() { + let c = composite!("application/json", "123", "text/plain", "ccc"); + let vv: Vec<_> = c + .iter() + .map(|it| { + format!( + "{}={}", + it.get_mime_type(), + it.get_metadata_utf8().unwrap_or_default() + ) + }) + .collect(); + assert_eq!(vv.join(","), "application/json=123,text/plain=ccc"); + } +} diff --git a/rsocket/src/macros/mod.rs b/rsocket/src/macros/mod.rs new file mode 100644 index 0000000..3074c0f --- /dev/null +++ b/rsocket/src/macros/mod.rs @@ -0,0 +1,4 @@ +#[macro_use] +mod composite; +#[macro_use] +mod routing; diff --git a/rsocket/src/macros/routing.rs b/rsocket/src/macros/routing.rs new file mode 100644 index 0000000..d24055e --- /dev/null +++ b/rsocket/src/macros/routing.rs @@ -0,0 +1,25 @@ +#[macro_export] +macro_rules! tags { + ($($v:expr),+) => { + { + let mut b = $crate::extension::RoutingMetadata::builder(); + $( + b = b.push_str($v); + )* + b.build() + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_routing() { + let t = tags!("a", "b", "c"); + let tags = t.get_tags(); + println!("{:?}", tags); + assert_eq!("a,b,c", t.get_tags().join(",")) + } +} diff --git a/rustfmt.toml b/rustfmt.toml index a75a838..5cc1634 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,3 +1,2 @@ edition = "2018" group_imports="StdExternalCrate" - From 65444d99572b06d24cae53c87f8abaed958f74d1 Mon Sep 17 00:00:00 2001 From: "caiweiwei.cww" Date: Thu, 13 May 2021 18:02:54 +0800 Subject: [PATCH 53/70] fix: check send error --- .gitignore | 2 +- examples/Cargo.toml | 3 +- examples/qps.rs | 25 +++++++++++ justfile | 2 +- rsocket-messaging/src/requester.rs | 8 ++-- rsocket/src/core/client.rs | 17 +++++--- rsocket/src/extension/composite.rs | 8 +--- rsocket/src/extension/mime.rs | 27 ++++++++---- rsocket/src/payload/setup.rs | 8 ++-- rsocket/src/transport/socket.rs | 66 ++++++++++++++++++++---------- 10 files changed, 113 insertions(+), 53 deletions(-) diff --git a/.gitignore b/.gitignore index 8aba189..75fee08 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,4 @@ target/ **/*.rs.bk Cargo.lock .vscode/ - +/flamegraph.svg diff --git a/examples/Cargo.toml b/examples/Cargo.toml index f564ddd..c5d6a1f 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -10,6 +10,7 @@ log = "0.4.13" env_logger = "0.8.2" futures = "0.3.10" clap = "2.33.3" +pprof = { version = "0.4", features = ["flamegraph"] } [dev-dependencies.rsocket_rust] path = "../rsocket" @@ -22,7 +23,7 @@ features = ["tls"] path = "../rsocket-transport-websocket" [dev-dependencies.tokio] -version = "1.0.1" +version = "1.0.3" default-features = false features = ["full"] diff --git a/examples/qps.rs b/examples/qps.rs index 920561b..66216f5 100644 --- a/examples/qps.rs +++ b/examples/qps.rs @@ -1,6 +1,7 @@ #[macro_use] extern crate log; +use std::fs::File; use std::sync::{ atomic::{AtomicU32, Ordering}, Arc, @@ -65,6 +66,13 @@ async fn main() -> Result<()> { .version("0.0.0") .author("Jeffsky ") .about("An QPS benchmark tool for RSocket.") + .arg( + Arg::with_name("pprof") + .long("pprof") + .required(false) + .takes_value(false) + .help("Enable pprof."), + ) .arg( Arg::with_name("count") .short("c") @@ -100,6 +108,12 @@ async fn main() -> Result<()> { .value_of("size") .map(|s| s.parse().expect("Invalid size!")) .unwrap(); + + let mut guard = None; + if cli.is_present("pprof") { + guard = Some(pprof::ProfilerGuard::new(100).unwrap()); + } + let addr = cli.value_of("URL").unwrap(); let notify = Arc::new(Notify::new()); @@ -145,5 +159,16 @@ async fn main() -> Result<()> { costs, 1000f64 * (count as f64) / (costs as f64) ); + + if let Some(guard) = guard { + match guard.report().build() { + Ok(report) => { + let file = File::create("flamegraph.svg").unwrap(); + report.flamegraph(file).unwrap(); + } + Err(_) => {} + }; + } + Ok(()) } diff --git a/justfile b/justfile index 36b565b..5fceac2 100644 --- a/justfile +++ b/justfile @@ -13,4 +13,4 @@ fmt: echo: @RUST_LOG=release cargo run --release --example echo -- serve tcp://127.0.0.1:7878 bench: - @RUST_LOG=info cargo run --release --example qps -- -c 1000000 -s 1024 tcp://127.0.0.1:7878 + @RUST_LOG=info cargo run --release --example qps -- -c 1000000 -s 1024 --pprof tcp://127.0.0.1:7878 diff --git a/rsocket-messaging/src/requester.rs b/rsocket-messaging/src/requester.rs index 088141a..c252d40 100644 --- a/rsocket-messaging/src/requester.rs +++ b/rsocket-messaging/src/requester.rs @@ -155,9 +155,9 @@ impl RequesterBuilder { Some(TransportKind::TCP(h, p)) => { let addr: SocketAddr = format!("{}:{}", h, p).parse()?; let cli = RSocketFactory::connect() - .data_mime_type(data_mime_type.as_ref()) + .data_mime_type(data_mime_type) .setup(setup) - .metadata_mime_type(MimeType::MESSAGE_X_RSOCKET_COMPOSITE_METADATA_V0.as_ref()) + .metadata_mime_type(MimeType::MESSAGE_X_RSOCKET_COMPOSITE_METADATA_V0) .transport(TcpClientTransport::from(addr)) .start() .await?; @@ -168,9 +168,9 @@ impl RequesterBuilder { Some(TransportKind::WS(u)) => { let url = Url::parse(&u)?; let cli = RSocketFactory::connect() - .data_mime_type(data_mime_type.as_ref()) + .data_mime_type(data_mime_type) .setup(setup) - .metadata_mime_type(MimeType::MESSAGE_X_RSOCKET_COMPOSITE_METADATA_V0.as_ref()) + .metadata_mime_type(MimeType::MESSAGE_X_RSOCKET_COMPOSITE_METADATA_V0) .transport(WebsocketClientTransport::from(url)) .start() .await?; diff --git a/rsocket/src/core/client.rs b/rsocket/src/core/client.rs index 65157ef..f846bb9 100644 --- a/rsocket/src/core/client.rs +++ b/rsocket/src/core/client.rs @@ -52,9 +52,10 @@ where pub fn fragment(mut self, mtu: usize) -> Self { if mtu > 0 && mtu < transport::MIN_MTU { - panic!("invalid fragment mtu: at least {}!", transport::MIN_MTU) + warn!("invalid fragment mtu: at least {}!", transport::MIN_MTU) + } else { + self.mtu = mtu; } - self.mtu = mtu; self } @@ -82,18 +83,22 @@ where self } - pub fn mime_type(mut self, metadata_mime_type: &str, data_mime_type: &str) -> Self { + pub fn mime_type( + mut self, + metadata_mime_type: impl Into, + data_mime_type: impl Into, + ) -> Self { self = self.metadata_mime_type(metadata_mime_type); self = self.data_mime_type(data_mime_type); self } - pub fn data_mime_type(mut self, mime_type: &str) -> Self { + pub fn data_mime_type(mut self, mime_type: impl Into) -> Self { self.setup = self.setup.set_data_mime_type(mime_type); self } - pub fn metadata_mime_type(mut self, mime_type: &str) -> Self { + pub fn metadata_mime_type(mut self, mime_type: impl Into) -> Self { self.setup = self.setup.set_metadata_mime_type(mime_type); self } @@ -232,7 +237,7 @@ where } }); - socket.setup(setup).await; + socket.setup(setup).await?; Ok(Client::new(socket, close_notify, closing)) } diff --git a/rsocket/src/extension/composite.rs b/rsocket/src/extension/composite.rs index 239b7af..1ad7663 100644 --- a/rsocket/src/extension/composite.rs +++ b/rsocket/src/extension/composite.rs @@ -119,13 +119,7 @@ impl CompositeMetadata { let mime_type = if 0x80 & first != 0 { // Well let n = first & 0x7F; - match MimeType::parse(n) { - Some(well) => well, - None => { - let err_str = format!("invalid Well-Known MIME type: identifier={:x}", n); - return Err(RSocketError::WithDescription(err_str).into()); - } - } + MimeType::WellKnown(n) } else { // Bad let mime_len = (first as usize) + 1; diff --git a/rsocket/src/extension/mime.rs b/rsocket/src/extension/mime.rs index 8138b95..8b0d7d4 100644 --- a/rsocket/src/extension/mime.rs +++ b/rsocket/src/extension/mime.rs @@ -1,8 +1,12 @@ use std::collections::HashMap; +use std::convert::TryInto; use std::fmt; use once_cell::sync::Lazy; +use crate::error::RSocketError; +use crate::Result; + #[derive(PartialEq, Eq, Debug, Clone, Hash)] pub enum MimeType { Normal(String), @@ -36,19 +40,26 @@ impl MimeType { Self::Normal(_) => None, } } -} -impl Into for MimeType { - fn into(self) -> String { - self.as_ref().to_owned() + pub fn as_str(&self) -> Option<&str> { + match self { + Self::Normal(s) => Some(s.as_ref()), + Self::WellKnown(n) => match U8_TO_STR.get(n) { + Some(v) => Some(v), + None => None, + }, + } } } -impl AsRef for MimeType { - fn as_ref(&self) -> &str { +impl Into for MimeType { + fn into(self) -> String { match self { - Self::Normal(s) => &s, - Self::WellKnown(n) => U8_TO_STR.get(n).unwrap(), + Self::Normal(s) => s, + Self::WellKnown(n) => match U8_TO_STR.get(&n) { + Some(v) => v.to_string(), + None => "UNKNOWN".to_string(), + }, } } } diff --git a/rsocket/src/payload/setup.rs b/rsocket/src/payload/setup.rs index 8d25d92..8c69b7e 100644 --- a/rsocket/src/payload/setup.rs +++ b/rsocket/src/payload/setup.rs @@ -86,12 +86,12 @@ impl SetupPayloadBuilder { self } - pub fn set_data_mime_type(mut self, mime: &str) -> Self { - self.inner.mime_d = Some(Bytes::from(mime.to_owned())); + pub fn set_data_mime_type(mut self, mime: impl Into) -> Self { + self.inner.mime_d = Some(Bytes::from(mime.into())); self } - pub fn set_metadata_mime_type(mut self, mime: &str) -> Self { - self.inner.mime_m = Some(Bytes::from(mime.to_owned())); + pub fn set_metadata_mime_type(mut self, mime: impl Into) -> Self { + self.inner.mime_m = Some(Bytes::from(mime.into())); self } diff --git a/rsocket/src/transport/socket.rs b/rsocket/src/transport/socket.rs index 4cbb302..2e34e65 100644 --- a/rsocket/src/transport/socket.rs +++ b/rsocket/src/transport/socket.rs @@ -69,7 +69,7 @@ impl DuplexSocket { socket } - pub(crate) async fn setup(&mut self, setup: SetupPayload) { + pub(crate) async fn setup(&mut self, setup: SetupPayload) -> Result<()> { let mut bu = frame::Setup::builder(0, 0); if let Some(s) = setup.data_mime_type() { bu = bu.set_mime_data(s); @@ -86,7 +86,7 @@ impl DuplexSocket { if let Some(b) = m { bu = bu.set_metadata(b); } - self.tx.send(bu.build()).expect("Send setup failed"); + self.tx.send(bu.build()).map_err(|e| e.into()) } #[inline] @@ -128,7 +128,9 @@ impl DuplexSocket { .set_code(error::ERR_REJECT_SETUP) .set_data(Bytes::from(errmsg)) .build(); - self.tx.send(sending).expect("Reject setup failed"); + if let Err(_) = self.tx.send(sending) { + error!("Reject setup failed"); + } return; } } @@ -261,13 +263,28 @@ impl DuplexSocket { self.joiners.remove(&sid); // pick handler if let Some((_, handler)) = self.handlers.remove(&sid) { - let desc = input.get_data_utf8().unwrap().to_owned(); + let desc = input + .get_data_utf8() + .map(|it| it.to_string()) + .unwrap_or_default(); let e = RSocketError::must_new_from_code(input.get_code(), desc); match handler { - Handler::ReqRR(tx) => tx.send(Err(e.into())).expect("Send RR failed"), + Handler::ReqRR(tx) => { + if let Err(_) = tx.send(Err(e.into())) { + error!("respond with error for REQUEST_RESPONSE failed!"); + } + } Handler::ResRR(_) => unreachable!(), - Handler::ReqRS(tx) => tx.send(Err(e.into())).await.expect("Send RS failed"), - Handler::ReqRC(tx) => tx.send(Err(e.into())).await.expect("Send RC failed"), + Handler::ReqRS(tx) => { + if let Err(_) = tx.send(Err(e.into())).await { + error!("respond with error for REQUEST_STREAM failed!"); + }; + } + Handler::ReqRC(tx) => { + if let Err(_) = tx.send(Err(e.into())).await { + error!("respond with error for REQUEST_CHANNEL failed!"); + } + } } } } @@ -281,7 +298,9 @@ impl DuplexSocket { match handler { Handler::ReqRR(sender) => { info!("REQUEST_RESPONSE {} cancelled!", sid); - sender.send(e).unwrap(); + if let Err(_) = sender.send(e) { + error!("notify cancel for REQUEST_RESPONSE failed: sid={}", sid); + } } Handler::ResRR(c) => { let lefts = c.count_down(); @@ -305,9 +324,13 @@ impl DuplexSocket { Handler::ReqRR(_) => match o.remove() { Handler::ReqRR(sender) => { if flag & Frame::FLAG_NEXT != 0 { - sender.send(Ok(Some(input))).unwrap(); + if let Err(_) = sender.send(Ok(Some(input))) { + error!("response successful payload for REQUEST_RESPONSE failed: sid={}",sid); + } } else { - sender.send(Ok(None)).unwrap(); + if let Err(_) = sender.send(Ok(None)) { + error!("response successful payload for REQUEST_RESPONSE failed: sid={}",sid); + } } } _ => unreachable!(), @@ -315,11 +338,12 @@ impl DuplexSocket { Handler::ResRR(c) => unreachable!(), Handler::ReqRS(sender) => { if flag & Frame::FLAG_NEXT != 0 { - sender - .clone() - .send(Ok(input)) - .await - .expect("Send payload response failed."); + if let Err(e) = sender.send(Ok(input)).await { + error!( + "response successful payload for REQUEST_STREAM failed: sid={}", + sid + ); + } } if flag & Frame::FLAG_COMPLETE != 0 { o.remove(); @@ -328,11 +352,9 @@ impl DuplexSocket { Handler::ReqRC(sender) => { // TODO: support channel if flag & Frame::FLAG_NEXT != 0 { - sender - .clone() - .send(Ok(input)) - .await - .expect("Send payload response failed"); + if let Err(_) = sender.clone().send(Ok(input)).await { + error!("response successful payload for REQUEST_CHANNEL failed: sid={}",sid); + } } if flag & Frame::FLAG_COMPLETE != 0 { o.remove(); @@ -396,7 +418,9 @@ impl DuplexSocket { } // async remove canceller - canceller.send(sid).await.expect("Send canceller failed"); + if let Err(_) = canceller.send(sid).await { + error!("Send canceller failed: sid={}", sid); + } match result { Ok(Some(res)) => { From 38ff36a5af2b0b7cd3738b05227b67a7d3a1d0f4 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Thu, 13 May 2021 19:06:02 +0800 Subject: [PATCH 54/70] chore: upgrade deps --- examples/Cargo.toml | 8 ++++---- rsocket-test/Cargo.toml | 16 ++++++++-------- rsocket-transport-tcp/Cargo.toml | 6 +++--- rsocket-transport-wasm/Cargo.toml | 17 ++++++++--------- rsocket-transport-wasm/src/client.rs | 3 +-- rsocket-transport-websocket/Cargo.toml | 4 ++-- rsocket/Cargo.toml | 18 +++++++++--------- 7 files changed, 35 insertions(+), 37 deletions(-) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index c5d6a1f..6219774 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -6,11 +6,11 @@ edition = "2018" publish = false [dev-dependencies] -log = "0.4.13" -env_logger = "0.8.2" -futures = "0.3.10" +log = "0.4.14" +env_logger = "0.8.3" +futures = "0.3.15" clap = "2.33.3" -pprof = { version = "0.4", features = ["flamegraph"] } +pprof = { version = "0.4.3", features = ["flamegraph"] } [dev-dependencies.rsocket_rust] path = "../rsocket" diff --git a/rsocket-test/Cargo.toml b/rsocket-test/Cargo.toml index 3474fb4..0c73a80 100644 --- a/rsocket-test/Cargo.toml +++ b/rsocket-test/Cargo.toml @@ -6,14 +6,14 @@ edition = "2018" publish = false [dev-dependencies] -log = "0.4" -futures = "0.3.10" -env_logger = "0.8.2" +log = "0.4.14" +futures = "0.3.15" +env_logger = "0.8.3" bytes = "1.0.1" -hex = "0.4.2" -rand = "0.8.2" -serde = "1.0.119" -serde_derive = "1.0.119" +hex = "0.4.3" +rand = "0.8.3" +serde = "1.0.126" +serde_derive = "1.0.126" [dev-dependencies.rsocket_rust] path = "../rsocket" @@ -29,6 +29,6 @@ path = "../rsocket-transport-websocket" path = "../rsocket-messaging" [dev-dependencies.tokio] -version = "1.0.1" +version = "1.0.3" default-features = false features = ["full"] diff --git a/rsocket-transport-tcp/Cargo.toml b/rsocket-transport-tcp/Cargo.toml index 4e166b4..a9ccd24 100644 --- a/rsocket-transport-tcp/Cargo.toml +++ b/rsocket-transport-tcp/Cargo.toml @@ -15,9 +15,9 @@ tls = ["tokio-native-tls"] [dependencies] log = "0.4.14" -futures = "0.3.13" +futures = "0.3.15" bytes = "1.0.1" -cfg-if = "1" +cfg-if = "1.0.0" [dependencies.rsocket_rust] path = "../rsocket" @@ -29,7 +29,7 @@ default-features = false features = [ "rt", "rt-multi-thread", "net", "sync", "io-util", "macros" ] [dependencies.tokio-util] -version = "0.6.3" +version = "0.6.6" default-features = false features = ["codec"] diff --git a/rsocket-transport-wasm/Cargo.toml b/rsocket-transport-wasm/Cargo.toml index 5435a24..354a86f 100644 --- a/rsocket-transport-wasm/Cargo.toml +++ b/rsocket-transport-wasm/Cargo.toml @@ -11,13 +11,12 @@ description = "WASM Websocket RSocket transport implementation." [dependencies] bytes = "1.0.1" -wasm-bindgen-futures = "0.4.20" -futures-channel = "0.3.13" -futures-util = "0.3.13" -js-sys = "0.3.47" -serde = "1.0.123" -serde_derive = "1.0.123" -async-trait = "0.1.42" +wasm-bindgen-futures = "0.4.24" +futures-channel = "0.3.15" +futures-util = "0.3.15" +js-sys = "0.3.51" +serde = "1.0.126" +serde_derive = "1.0.126" log = "0.4.14" [dependencies.rsocket_rust] @@ -25,11 +24,11 @@ path = "../rsocket" features = ["frame"] [dependencies.wasm-bindgen] -version = "0.2.70" +version = "0.2.74" features = ["serde-serialize"] [dependencies.web-sys] -version = "0.3.47" +version = "0.3.51" features = [ "FileReader", "ProgressEvent", diff --git a/rsocket-transport-wasm/src/client.rs b/rsocket-transport-wasm/src/client.rs index 89a00df..9333be5 100644 --- a/rsocket-transport-wasm/src/client.rs +++ b/rsocket-transport-wasm/src/client.rs @@ -2,7 +2,6 @@ use std::cell::RefCell; use std::future::Future; use std::rc::Rc; -use async_trait::async_trait; use bytes::BytesMut; use futures_channel::{mpsc, oneshot}; use futures_util::StreamExt; @@ -10,7 +9,7 @@ use js_sys::{ArrayBuffer, Uint8Array}; use rsocket_rust::frame::Frame; use rsocket_rust::transport::Transport; use rsocket_rust::utils::Writeable; -use rsocket_rust::{error::RSocketError, Result}; +use rsocket_rust::{async_trait, error::RSocketError, Result}; use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; use web_sys::{ErrorEvent, Event, FileReader, MessageEvent, ProgressEvent, WebSocket}; diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index 4e8f7fe..e7e203d 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -11,9 +11,9 @@ description = "Websocket RSocket transport implementation." [dependencies] log = "0.4.14" -futures = "0.3.13" +futures = "0.3.15" bytes = "1.0.1" -url = "2.2.1" +url = "2.2.2" tokio-tungstenite = "0.13.0" [dependencies.rsocket_rust] diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index 3538acb..5544f30 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -10,19 +10,19 @@ homepage = "https://github.com/rsocket/rsocket-rust" description = "rsocket-rust is an implementation of the RSocket protocol in Rust." [dependencies] -log = "0.4.13" +log = "0.4.14" bytes = "1.0.1" -futures = "0.3.10" -once_cell = "1.6.0" -async-trait = "0.1.42" +futures = "0.3.15" +once_cell = "1.7.2" +async-trait = "0.1.50" dashmap = "4.0.2" -thiserror = "1.0.23" -anyhow = "1.0.38" -async-stream = "0.3.0" -cfg-if = "1" +thiserror = "1.0.24" +anyhow = "1.0.40" +async-stream = "0.3.1" +cfg-if = "1.0.0" [target.'cfg(target_arch = "wasm32")'.dependencies] -wasm-bindgen-futures = "0.4.19" +wasm-bindgen-futures = "0.4.24" [dependencies.tokio] version = "1.0.3" From c977f9442a23b9594d3f60a2b497d4efe8d98720 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Thu, 13 May 2021 19:29:30 +0800 Subject: [PATCH 55/70] Release/0.7.1 (#45) * ci: prepare v0.7.1 * ci: prepare v0.7.1 * ci: prepare v0.7.1 --- examples/Cargo.toml | 9 ++++++--- rsocket-messaging/Cargo.toml | 9 ++++++--- rsocket-test/Cargo.toml | 12 ++++++++---- rsocket-transport-tcp/Cargo.toml | 3 ++- rsocket-transport-wasm/Cargo.toml | 3 ++- rsocket-transport-websocket/Cargo.toml | 3 ++- 6 files changed, 26 insertions(+), 13 deletions(-) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 6219774..1d090fb 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -13,14 +13,17 @@ clap = "2.33.3" pprof = { version = "0.4.3", features = ["flamegraph"] } [dev-dependencies.rsocket_rust] -path = "../rsocket" +version = "0.7.1" +# path = "../rsocket" [dev-dependencies.rsocket_rust_transport_tcp] -path = "../rsocket-transport-tcp" +version = "0.7.1" +# path = "../rsocket-transport-tcp" features = ["tls"] [dev-dependencies.rsocket_rust_transport_websocket] -path = "../rsocket-transport-websocket" +version = "0.7.1" +# path = "../rsocket-transport-websocket" [dev-dependencies.tokio] version = "1.0.3" diff --git a/rsocket-messaging/Cargo.toml b/rsocket-messaging/Cargo.toml index c464f8a..c38714e 100644 --- a/rsocket-messaging/Cargo.toml +++ b/rsocket-messaging/Cargo.toml @@ -19,11 +19,14 @@ hex = "0.4.2" url = "2.2.0" [dependencies.rsocket_rust] -path = "../rsocket" +version = "0.7.1" +# path = "../rsocket" features = ["frame"] [dependencies.rsocket_rust_transport_tcp] -path = "../rsocket-transport-tcp" +version = "0.7.1" +# path = "../rsocket-transport-tcp" [dependencies.rsocket_rust_transport_websocket] -path = "../rsocket-transport-websocket" +version = "0.7.1" +# path = "../rsocket-transport-websocket" diff --git a/rsocket-test/Cargo.toml b/rsocket-test/Cargo.toml index 0c73a80..34c3a50 100644 --- a/rsocket-test/Cargo.toml +++ b/rsocket-test/Cargo.toml @@ -16,17 +16,21 @@ serde = "1.0.126" serde_derive = "1.0.126" [dev-dependencies.rsocket_rust] -path = "../rsocket" +version = "0.7.1" +# path = "../rsocket" features = ["frame"] [dev-dependencies.rsocket_rust_transport_tcp] -path = "../rsocket-transport-tcp" +version = "0.7.1" +# path = "../rsocket-transport-tcp" [dev-dependencies.rsocket_rust_transport_websocket] -path = "../rsocket-transport-websocket" +version = "0.7.1" +# path = "../rsocket-transport-websocket" [dev-dependencies.rsocket_rust_messaging] -path = "../rsocket-messaging" +version = "0.7.1" +# path = "../rsocket-messaging" [dev-dependencies.tokio] version = "1.0.3" diff --git a/rsocket-transport-tcp/Cargo.toml b/rsocket-transport-tcp/Cargo.toml index a9ccd24..2b83de9 100644 --- a/rsocket-transport-tcp/Cargo.toml +++ b/rsocket-transport-tcp/Cargo.toml @@ -20,7 +20,8 @@ bytes = "1.0.1" cfg-if = "1.0.0" [dependencies.rsocket_rust] -path = "../rsocket" +version = "0.7.1" +# path = "../rsocket" features = ["frame"] [dependencies.tokio] diff --git a/rsocket-transport-wasm/Cargo.toml b/rsocket-transport-wasm/Cargo.toml index 354a86f..10c38d1 100644 --- a/rsocket-transport-wasm/Cargo.toml +++ b/rsocket-transport-wasm/Cargo.toml @@ -20,7 +20,8 @@ serde_derive = "1.0.126" log = "0.4.14" [dependencies.rsocket_rust] -path = "../rsocket" +version = "0.7.1" +# path = "../rsocket" features = ["frame"] [dependencies.wasm-bindgen] diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index e7e203d..caca2a4 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -17,7 +17,8 @@ url = "2.2.2" tokio-tungstenite = "0.13.0" [dependencies.rsocket_rust] -path = "../rsocket" +version = "0.7.1" +# path = "../rsocket" features = ["frame"] [dependencies.tokio] From a5118c38c4fa526115609f4f2aee5d9d196aa385 Mon Sep 17 00:00:00 2001 From: "fuchen.ljl" Date: Mon, 31 May 2021 20:34:24 +0800 Subject: [PATCH 56/70] chore: update dependencies for readme (#46) Update dependencies --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9242242..52f3c41 100644 --- a/README.md +++ b/README.md @@ -21,12 +21,12 @@ Add dependencies in your `Cargo.toml`. ```toml [dependencies] -tokio = "1.0" -rsocket_rust = "0.7" +tokio = "1.0.3" +rsocket_rust = "0.7.1" # add transport dependencies: -# rsocket_rust_transport_tcp = "0.7" -# rsocket_rust_transport_websocket = "0.7" +# rsocket_rust_transport_tcp = "0.7.1" +# rsocket_rust_transport_websocket = "0.7.1" ``` ### Server From 0e4530bd87ec86350ad21c6be75417ea99c9a8e0 Mon Sep 17 00:00:00 2001 From: "fuchen.ljl" Date: Mon, 31 May 2021 20:43:41 +0800 Subject: [PATCH 57/70] chore: update example code in readme (#47) Replace cli & proxy.rs in Example --- README.md | 58 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 52f3c41..797a0ec 100644 --- a/README.md +++ b/README.md @@ -32,22 +32,32 @@ rsocket_rust = "0.7.1" ### Server ```rust +extern crate log; + +use futures::executor::block_on; use rsocket_rust::prelude::*; use rsocket_rust::utils::EchoRSocket; use rsocket_rust::Result; -use rsocket_rust_transport_tcp::TcpServerTransport; +use rsocket_rust_transport_tcp::*; #[tokio::main] async fn main() -> Result<()> { + env_logger::builder().format_timestamp_millis().init(); + RSocketFactory::receive() - .transport(TcpServerTransport::from("127.0.0.1:7878")) - .acceptor(Box::new(|setup, _socket| { - println!("accept setup: {:?}", setup); - Ok(Box::new(EchoRSocket)) - // Or you can reject setup - // Err(From::from("SETUP_NOT_ALLOW")) + .transport(TcpServerTransport::from("127.0.0.1:7979")) + .acceptor(Box::new(|setup, _sending_socket| { + info!("incoming socket: setup={:?}", setup); + Ok(Box::new(block_on(async move { + RSocketFactory::connect() + .transport(TcpClientTransport::from("127.0.0.1:7878")) + .acceptor(Box::new(|| Box::new(EchoRSocket))) + .setup(Payload::from("I'm Rust!")) + .start() + .await + .unwrap() + }))) })) - .on_start(Box::new(|| println!("+++++++ echo server started! +++++++"))) .serve() .await } @@ -56,28 +66,32 @@ async fn main() -> Result<()> { ### Client ```rust +extern crate log; + use rsocket_rust::prelude::*; +use rsocket_rust::utils::EchoRSocket; use rsocket_rust::Result; use rsocket_rust_transport_tcp::TcpClientTransport; #[tokio::main] async fn main() -> Result<()> { - let cli = RSocketFactory::connect() + env_logger::builder().format_timestamp_millis().init(); + let client = RSocketFactory::connect() .transport(TcpClientTransport::from("127.0.0.1:7878")) - .setup(Payload::from("READY!")) - .mime_type("text/plain", "text/plain") - .on_close(Box::new(|| println!("connection closed"))) + .acceptor(Box::new(|| { + // Return a responder. + Box::new(EchoRSocket) + })) .start() - .await?; - let req = Payload::builder() - .set_data_utf8("Hello World!") - .set_metadata_utf8("Rust") - .build(); - let res = cli.request_response(req).await?; - println!("got: {:?}", res); - - // If you want to block until socket disconnected. - cli.wait_for_close().await; + .await + .expect("Connect failed!"); + + let req = Payload::builder().set_data_utf8("Ping!").build(); + + match client.request_response(req).await { + Ok(res) => info!("{:?}", res), + Err(e) => error!("{}", e), + } Ok(()) } From efad3625d574489ccc9d4000fd1c8ce3b6625c2a Mon Sep 17 00:00:00 2001 From: Yuriy Kulikov <827794+yuriykulikov@users.noreply.github.com> Date: Wed, 1 Sep 2021 14:57:42 +0200 Subject: [PATCH 58/70] feat: implemented cancel frame handling (#49) Client will send a CANCEL frame for a dropped stream when the next payload is received for this stream. --- Cargo.toml | 4 + rsocket-test/Cargo.toml | 16 + .../tests/test_stream_cancellation.rs | 334 ++++++++++++++++++ rsocket/Cargo.toml | 4 + rsocket/src/transport/socket.rs | 46 ++- 5 files changed, 399 insertions(+), 5 deletions(-) create mode 100644 rsocket-test/tests/test_stream_cancellation.rs diff --git a/Cargo.toml b/Cargo.toml index 36f0b94..0ab48d8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,3 +9,7 @@ members = [ "examples", "rsocket-test", ] + +[replace] +"rsocket_rust:0.7.1" = { path = "../rsocket-rust/rsocket" } +"rsocket_rust_transport_tcp:0.7.1" = { path = "../rsocket-rust/rsocket-transport-tcp" } diff --git a/rsocket-test/Cargo.toml b/rsocket-test/Cargo.toml index 34c3a50..2f63d38 100644 --- a/rsocket-test/Cargo.toml +++ b/rsocket-test/Cargo.toml @@ -36,3 +36,19 @@ version = "0.7.1" version = "1.0.3" default-features = false features = ["full"] + +[dev-dependencies.tokio-stream] +version = "0.1.7" +features = ["sync"] + +[dev-dependencies.anyhow] +version = "1.0.40" + +[dev-dependencies.async-trait] +version = "0.1.50" + +[dev-dependencies.serial_test] +version = "0.5.1" + +[dev-dependencies.async-stream] +version = "0.3.1" diff --git a/rsocket-test/tests/test_stream_cancellation.rs b/rsocket-test/tests/test_stream_cancellation.rs new file mode 100644 index 0000000..08a8bad --- /dev/null +++ b/rsocket-test/tests/test_stream_cancellation.rs @@ -0,0 +1,334 @@ +#[macro_use] +extern crate log; + +use std::sync::Arc; +use std::sync::Mutex; +use std::time::Duration; + +use anyhow::Result; +use async_trait::async_trait; +use futures::StreamExt; +use tokio_stream::wrappers::ReceiverStream; + +use rsocket_rust::prelude::{Flux, Payload, RSocket}; + +#[cfg(test)] +mod tests { + use std::time::Duration; + + use futures::Future; + use rsocket_rust_transport_websocket::{WebsocketClientTransport, WebsocketServerTransport}; + use serial_test::serial; + use tokio::runtime::Runtime; + use async_stream::stream; + use rsocket_rust::Client; + use rsocket_rust::prelude::*; + use rsocket_rust::utils::EchoRSocket; + use rsocket_rust_transport_tcp::{TcpClientTransport, TcpServerTransport, UnixClientTransport, UnixServerTransport}; + + use crate::TestSocket; + + #[serial] + #[test] + fn request_stream_can_be_cancelled_by_client_uds() { + init_logger(); + with_uds_test_socket_run(request_stream_can_be_cancelled_by_client); + } + + #[serial] + #[test] + fn request_stream_can_be_cancelled_by_client_tcp() { + init_logger(); + with_tcp_test_socket_run(request_stream_can_be_cancelled_by_client); + } + + #[serial] + #[test] + fn request_stream_can_be_cancelled_by_client_ws() { + init_logger(); + with_ws_test_socket_run(request_stream_can_be_cancelled_by_client); + } + + /// + /// Client requests a channel, consumes an item and drops the stream handle. + /// + /// Amount of active streams is verified before and after requesting and after dropping. + /// + /// Before request_stream: 0 subscribers + /// When request_stream is called: 1 subscriber + /// When request_stream handle is dropped: 0 subscribers + async fn request_stream_can_be_cancelled_by_client(client: Client) { + assert_eq!( + client.request_response(Payload::from("subscribers")).await.unwrap().unwrap().data_utf8(), + Some("0") + ); + + let mut results = client.request_stream(Payload::from("")); + let payload = results.next().await.expect("valid payload").unwrap(); + assert_eq!(payload.metadata_utf8(), Some("subscribers: 1")); + assert_eq!(payload.data_utf8(), Some("0")); + + assert_eq!( + client.request_response(Payload::from("subscribers")).await.unwrap().unwrap().data_utf8(), + Some("1") + ); + + debug!("when the Flux is dropped"); + drop(results); + // Give the server enough time to receive the CANCEL frame + tokio::time::sleep(Duration::from_millis(250)).await; + + assert_eq!( + client.request_response(Payload::from("subscribers")).await.unwrap().unwrap().data_utf8(), + Some("0") + ); + } + + #[serial] + #[test] + fn request_channel_can_be_cancelled_by_client_uds() { + init_logger(); + with_uds_test_socket_run(request_channel_can_be_cancelled_by_client); + } + + #[serial] + #[test] + fn request_channel_can_be_cancelled_by_client_tcp() { + init_logger(); + with_tcp_test_socket_run(request_channel_can_be_cancelled_by_client); + } + + #[serial] + #[test] + fn request_channel_can_be_cancelled_by_client_ws() { + init_logger(); + with_ws_test_socket_run(request_channel_can_be_cancelled_by_client); + } + + /// + /// Client requests a stream, consumes an item and drops the stream handle. + /// + /// Amount of active streams is verified before and after requesting and after dropping. + /// + /// Before request_channel: 0 subscribers + /// When request_channel is called: 1 subscriber + /// When request_channel handle is dropped: 0 subscribers + async fn request_channel_can_be_cancelled_by_client(client: Client) { + assert_eq!( + client.request_response(Payload::from("subscribers")).await.unwrap().unwrap().data_utf8(), + Some("0") + ); + + let mut results = client.request_channel( + stream!{ yield Ok(Payload::from("")) }.boxed() + ); + let payload = results.next().await.expect("valid payload").unwrap(); + assert_eq!(payload.metadata_utf8(), Some("subscribers: 1")); + assert_eq!(payload.data_utf8(), Some("0")); + + assert_eq!( + client.request_response(Payload::from("subscribers")).await.unwrap().unwrap().data_utf8(), + Some("1") + ); + + debug!("when the Flux is dropped"); + drop(results); + // Give the server enough time to receive the CANCEL frame + tokio::time::sleep(Duration::from_millis(250)).await; + + assert_eq!( + client.request_response(Payload::from("subscribers")).await.unwrap().unwrap().data_utf8(), + Some("0") + ); + } + + fn init_logger() { + let _ = env_logger::builder() + .format_timestamp_millis() + .filter_level(log::LevelFilter::Debug) + // .is_test(true) + .try_init(); + } + + /// Executes the [run_test] scenario using a client which is connected over a UDS transport to + /// a TestSocket + fn with_uds_test_socket_run(run_test: F) + where + F: (FnOnce(Client) -> Fut) + Send + 'static, + Fut: Future + Send + 'static, + { + info!("=====> begin uds"); + let server_runtime = Runtime::new().unwrap(); + + server_runtime.spawn(async move { + RSocketFactory::receive() + .transport(UnixServerTransport::from("/tmp/rsocket-uds.sock".to_owned())) + .acceptor(Box::new(|_setup, _socket| { Ok(Box::new(TestSocket::new())) })) + .serve() + .await + }); + + std::thread::sleep(Duration::from_millis(500)); + + let client_runtime = Runtime::new().unwrap(); + + client_runtime.block_on(async { + let client = RSocketFactory::connect() + .acceptor(Box::new(|| Box::new(EchoRSocket))) + .transport(UnixClientTransport::from("/tmp/rsocket-uds.sock".to_owned())) + .setup(Payload::from("READY!")) + .mime_type("text/plain", "text/plain") + .start() + .await + .unwrap(); + run_test(client).await; + }); + info!("<===== uds done!"); + } + + /// Executes the [run_test] scenario using a client which is connected over a UDS transport to + /// a TestSocket + fn with_ws_test_socket_run(run_test: F) + where + F: (FnOnce(Client) -> Fut) + Send + 'static, + Fut: Future + Send + 'static, + { + info!("=====> begin ws"); + let server_runtime = Runtime::new().unwrap(); + server_runtime.spawn(async move { + RSocketFactory::receive() + .transport(WebsocketServerTransport::from("127.0.0.1:8080".to_owned())) + .acceptor(Box::new(|_setup, _socket| { Ok(Box::new(TestSocket::new())) })) + .serve() + .await + }); + + std::thread::sleep(Duration::from_millis(500)); + + let client_runtime = Runtime::new().unwrap(); + + client_runtime.block_on(async { + let client = RSocketFactory::connect() + .acceptor(Box::new(|| Box::new(EchoRSocket))) + .transport(WebsocketClientTransport::from("127.0.0.1:8080")) + .setup(Payload::from("READY!")) + .mime_type("text/plain", "text/plain") + .start() + .await + .unwrap(); + + + run_test(client).await; + }); + info!("<===== ws done!"); + } + + /// Executes the [run_test] scenario using a client which is connected over a TCP transport to + /// a TestSocket + fn with_tcp_test_socket_run(run_test: F) + where + F: (FnOnce(Client) -> Fut) + Send + 'static, + Fut: Future + Send + 'static, + { + info!("=====> begin tcp"); + let server_runtime = Runtime::new().unwrap(); + server_runtime.spawn(async move { + RSocketFactory::receive() + .transport(TcpServerTransport::from("127.0.0.1:7878".to_owned())) + .acceptor(Box::new(|_setup, _socket| { Ok(Box::new(TestSocket::new())) })) + .serve() + .await + }); + + std::thread::sleep(Duration::from_millis(500)); + + let client_runtime = Runtime::new().unwrap(); + + client_runtime.block_on(async { + let client = RSocketFactory::connect() + .acceptor(Box::new(|| Box::new(EchoRSocket))) + .transport(TcpClientTransport::from("127.0.0.1:7878".to_owned())) + .setup(Payload::from("READY!")) + .mime_type("text/plain", "text/plain") + .start() + .await + .unwrap(); + run_test(client).await; + }); + info!("<===== tpc done!"); + } +} + +/// Stateful socket for tests, can be used to count active subscribers. +struct TestSocket { + subscribers: Arc>, +} + +impl TestSocket { + fn new() -> Self { + TestSocket { + subscribers: Arc::new(Mutex::new(0)), + } + } + + fn inc_subscriber_count(subscribers: &Arc>) { + let mut guard = subscribers.lock().unwrap(); + *guard = *guard + 1; + info!(target: "TestSocket", "subscribers:({})", guard); + } + + fn dec_subscriber_count(subscribers: &Arc>) { + let mut guard = subscribers.lock().unwrap(); + *guard = *guard - 1; + info!(target: "TestSocket", "subscribers:({})", guard); + } +} + +#[async_trait] +impl RSocket for TestSocket { + async fn metadata_push(&self, _req: Payload) -> Result<()> { + unimplemented!(); + } + + async fn fire_and_forget(&self, _req: Payload) -> Result<()> { + unimplemented!(); + } + + async fn request_response(&self, req: Payload) -> Result> { + let subscribers = *self.subscribers.lock().unwrap(); + let response = match req.data_utf8() { + Some("subscribers") => format!("{}", subscribers), + _ => "Request payload did not contain a known key!".to_owned(), + }; + Ok(Some(Payload::builder().set_data_utf8(&response).build())) + } + + fn request_stream(&self, _req: Payload) -> Flux> { + let (tx, rx) = tokio::sync::mpsc::channel(32); + let subscribers = self.subscribers.clone(); + tokio::spawn(async move { + TestSocket::inc_subscriber_count(&subscribers); + + for i in 0 as u32..100 { + if tx.is_closed() { + debug!(target: "TestSocket", "tx is closed, break!"); + break; + } + let payload = Payload::builder() + .set_data_utf8(format!("{}", i).as_str()) + .set_metadata_utf8(format!("subscribers: {}", *subscribers.lock().unwrap()).as_str()) + .build(); + tx.send(Ok(payload)).await.unwrap(); + tokio::time::sleep(Duration::from_millis(50)).await; + } + + TestSocket::dec_subscriber_count(&subscribers); + }); + + ReceiverStream::new(rx).boxed() + } + + fn request_channel(&self, _reqs: Flux>) -> Flux> { + self.request_stream(Payload::from("")) + } +} diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index 5544f30..0d00135 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -29,6 +29,10 @@ version = "1.0.3" default-features = false features = [ "macros", "rt", "rt-multi-thread", "sync", "time" ] +[dependencies.tokio-stream] +version = "0.1.7" +features = ["sync"] + [features] default = [] frame = [] diff --git a/rsocket/src/transport/socket.rs b/rsocket/src/transport/socket.rs index 2e34e65..4a139e8 100644 --- a/rsocket/src/transport/socket.rs +++ b/rsocket/src/transport/socket.rs @@ -7,6 +7,7 @@ use async_trait::async_trait; use bytes::{Buf, BufMut, Bytes, BytesMut}; use dashmap::{mapref::entry::Entry, DashMap}; use futures::{Sink, SinkExt, Stream, StreamExt}; +use futures::future::{AbortHandle, Abortable}; use tokio::sync::{mpsc, oneshot, RwLock}; use super::fragmentation::{Joiner, Splitter}; @@ -28,6 +29,8 @@ pub(crate) struct DuplexSocket { canceller: mpsc::Sender, splitter: Option, joiners: Arc>, + /// AbortHandles for streams and channels associated by sid + abort_handles: Arc>, } #[derive(Clone)] @@ -58,6 +61,7 @@ impl DuplexSocket { handlers: Arc::new(DashMap::new()), joiners: Arc::new(DashMap::new()), splitter, + abort_handles: Arc::new(DashMap::new()), }; let cloned_socket = socket.clone(); @@ -291,6 +295,9 @@ impl DuplexSocket { #[inline] async fn on_cancel(&mut self, sid: u32, _flag: u16) { + if let Some((sid,abort_handle)) = self.abort_handles.remove(&sid) { + abort_handle.abort(); + } self.joiners.remove(&sid); if let Some((_, handler)) = self.handlers.remove(&sid) { let e: Result<_> = @@ -338,11 +345,14 @@ impl DuplexSocket { Handler::ResRR(c) => unreachable!(), Handler::ReqRS(sender) => { if flag & Frame::FLAG_NEXT != 0 { - if let Err(e) = sender.send(Ok(input)).await { + if sender.is_closed() { + self.send_cancel_frame(sid); + } else if let Err(e) = sender.send(Ok(input)).await { error!( "response successful payload for REQUEST_STREAM failed: sid={}", sid ); + self.send_cancel_frame(sid); } } if flag & Frame::FLAG_COMPLETE != 0 { @@ -352,8 +362,11 @@ impl DuplexSocket { Handler::ReqRC(sender) => { // TODO: support channel if flag & Frame::FLAG_NEXT != 0 { - if let Err(_) = sender.clone().send(Ok(input)).await { + if sender.is_closed() { + self.send_cancel_frame(sid); + } else if let Err(_) = sender.clone().send(Ok(input)).await { error!("response successful payload for REQUEST_CHANNEL failed: sid={}",sid); + self.send_cancel_frame(sid); } } if flag & Frame::FLAG_COMPLETE != 0 { @@ -366,6 +379,14 @@ impl DuplexSocket { } } + #[inline] + fn send_cancel_frame(&self, sid: u32) { + let cancel_frame = frame::Cancel::builder(sid, Frame::FLAG_COMPLETE).build(); + if let Err(e) = self.tx.send(cancel_frame) { + error!("Sending CANCEL frame failed: sid={}, reason: {}", sid, e); + } + } + pub(crate) async fn bind_responder(&self, responder: Box) { self.responder.set(responder).await; } @@ -454,9 +475,14 @@ impl DuplexSocket { let responder = self.responder.clone(); let mut tx = self.tx.clone(); let splitter = self.splitter.clone(); + let abort_handles = self.abort_handles.clone(); runtime::spawn(async move { - // TODO: support cancel - let mut payloads = responder.request_stream(input); + let (abort_handle, abort_registration) = AbortHandle::new_pair(); + abort_handles.insert(sid, abort_handle); + let mut payloads = Abortable::new( + responder.request_stream(input), + abort_registration + ); while let Some(next) = payloads.next().await { match next { Ok(it) => { @@ -471,6 +497,7 @@ impl DuplexSocket { } }; } + abort_handles.remove(&sid); let complete = frame::Payload::builder(sid, Frame::FLAG_COMPLETE).build(); tx.send(complete) .expect("Send stream complete response failed"); @@ -484,13 +511,21 @@ impl DuplexSocket { let (sender, mut receiver) = mpsc::channel::>(32); sender.send(Ok(first)).await.expect("Send failed!"); self.register_handler(sid, Handler::ReqRC(sender)).await; + let abort_handles = self.abort_handles.clone(); runtime::spawn(async move { // respond client channel - let mut outputs = responder.request_channel(Box::pin(stream! { + let outputs = responder.request_channel(Box::pin(stream! { while let Some(it) = receiver.recv().await{ yield it; } })); + let (abort_handle, abort_registration) = AbortHandle::new_pair(); + abort_handles.insert(sid, abort_handle); + let mut outputs = Abortable::new( + outputs, + abort_registration + ); + // TODO: support custom RequestN. let request_n = frame::RequestN::builder(sid, 0).build(); @@ -518,6 +553,7 @@ impl DuplexSocket { }; tx.send(sending).expect("Send failed!"); } + abort_handles.remove(&sid); let complete = frame::Payload::builder(sid, Frame::FLAG_COMPLETE).build(); if let Err(e) = tx.send(complete) { error!("complete REQUEST_CHANNEL failed: {}", e); From d30c14795697c8409119e2707822869a436d2a0e Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Wed, 1 Sep 2021 21:23:51 +0800 Subject: [PATCH 59/70] chore: upgrade to 0.7.2 (#50) --- Cargo.toml | 4 ---- README.md | 16 ++++++++-------- examples/Cargo.toml | 9 +++------ rsocket-messaging/Cargo.toml | 11 ++++------- rsocket-test/Cargo.toml | 12 ++++-------- rsocket-transport-tcp/Cargo.toml | 5 ++--- rsocket-transport-wasm/Cargo.toml | 5 ++--- rsocket-transport-websocket/Cargo.toml | 5 ++--- rsocket/Cargo.toml | 2 +- 9 files changed, 26 insertions(+), 43 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0ab48d8..36f0b94 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,3 @@ members = [ "examples", "rsocket-test", ] - -[replace] -"rsocket_rust:0.7.1" = { path = "../rsocket-rust/rsocket" } -"rsocket_rust_transport_tcp:0.7.1" = { path = "../rsocket-rust/rsocket-transport-tcp" } diff --git a/README.md b/README.md index 797a0ec..a9af911 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ [![License](https://img.shields.io/github/license/rsocket/rsocket-rust.svg)](https://github.com/rsocket/rsocket-rust/blob/master/LICENSE) [![GitHub Release](https://img.shields.io/github/release-pre/rsocket/rsocket-rust.svg)](https://github.com/rsocket/rsocket-rust/releases) -> rsocket-rust is an implementation of the RSocket protocol in Rust(1.39+). -It's an **alpha** version and still under active development. -**Do not use it in a production environment!** +> rsocket-rust is an implementation of the RSocket protocol in Rust(1.39+). It's +> an **alpha** version and still under active development. **Do not use it in a +> production environment!** ## Example @@ -22,11 +22,11 @@ Add dependencies in your `Cargo.toml`. ```toml [dependencies] tokio = "1.0.3" -rsocket_rust = "0.7.1" +rsocket_rust = "0.7.2" # add transport dependencies: -# rsocket_rust_transport_tcp = "0.7.1" -# rsocket_rust_transport_websocket = "0.7.1" +# rsocket_rust_transport_tcp = "0.7.2" +# rsocket_rust_transport_websocket = "0.7.2" ``` ### Server @@ -101,7 +101,8 @@ async fn main() -> Result<()> { Example for access Redis([crates](https://crates.io/crates/redis)): -> NOTICE: add dependency in Cargo.toml => redis = { version = "0.19.0", features = [ "aio" ] } +> NOTICE: add dependency in Cargo.toml => redis = { version = "0.19.0", features +> = [ "aio" ] } ```rust use std::str::FromStr; @@ -159,7 +160,6 @@ impl RSocket for RedisDao { todo!() } } - ``` ## TODO diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 1d090fb..935fb91 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -13,17 +13,14 @@ clap = "2.33.3" pprof = { version = "0.4.3", features = ["flamegraph"] } [dev-dependencies.rsocket_rust] -version = "0.7.1" -# path = "../rsocket" +version = "0.7" [dev-dependencies.rsocket_rust_transport_tcp] -version = "0.7.1" -# path = "../rsocket-transport-tcp" +version = "0.7" features = ["tls"] [dev-dependencies.rsocket_rust_transport_websocket] -version = "0.7.1" -# path = "../rsocket-transport-websocket" +version = "0.7" [dev-dependencies.tokio] version = "1.0.3" diff --git a/rsocket-messaging/Cargo.toml b/rsocket-messaging/Cargo.toml index c38714e..8864b15 100644 --- a/rsocket-messaging/Cargo.toml +++ b/rsocket-messaging/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_messaging" -version = "0.7.1" +version = "0.7.2" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" @@ -19,14 +19,11 @@ hex = "0.4.2" url = "2.2.0" [dependencies.rsocket_rust] -version = "0.7.1" -# path = "../rsocket" +version = "0.7" features = ["frame"] [dependencies.rsocket_rust_transport_tcp] -version = "0.7.1" -# path = "../rsocket-transport-tcp" +version = "0.7" [dependencies.rsocket_rust_transport_websocket] -version = "0.7.1" -# path = "../rsocket-transport-websocket" +version = "0.7" diff --git a/rsocket-test/Cargo.toml b/rsocket-test/Cargo.toml index 2f63d38..dc3f4a1 100644 --- a/rsocket-test/Cargo.toml +++ b/rsocket-test/Cargo.toml @@ -16,21 +16,17 @@ serde = "1.0.126" serde_derive = "1.0.126" [dev-dependencies.rsocket_rust] -version = "0.7.1" -# path = "../rsocket" +version = "0.7" features = ["frame"] [dev-dependencies.rsocket_rust_transport_tcp] -version = "0.7.1" -# path = "../rsocket-transport-tcp" +version = "0.7" [dev-dependencies.rsocket_rust_transport_websocket] -version = "0.7.1" -# path = "../rsocket-transport-websocket" +version = "0.7" [dev-dependencies.rsocket_rust_messaging] -version = "0.7.1" -# path = "../rsocket-messaging" +version = "0.7" [dev-dependencies.tokio] version = "1.0.3" diff --git a/rsocket-transport-tcp/Cargo.toml b/rsocket-transport-tcp/Cargo.toml index 2b83de9..0dbe4fc 100644 --- a/rsocket-transport-tcp/Cargo.toml +++ b/rsocket-transport-tcp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_tcp" -version = "0.7.1" +version = "0.7.2" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" @@ -20,8 +20,7 @@ bytes = "1.0.1" cfg-if = "1.0.0" [dependencies.rsocket_rust] -version = "0.7.1" -# path = "../rsocket" +version = "0.7" features = ["frame"] [dependencies.tokio] diff --git a/rsocket-transport-wasm/Cargo.toml b/rsocket-transport-wasm/Cargo.toml index 10c38d1..991f11e 100644 --- a/rsocket-transport-wasm/Cargo.toml +++ b/rsocket-transport-wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_wasm" -version = "0.7.1" +version = "0.7.2" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" @@ -20,8 +20,7 @@ serde_derive = "1.0.126" log = "0.4.14" [dependencies.rsocket_rust] -version = "0.7.1" -# path = "../rsocket" +version = "0.7" features = ["frame"] [dependencies.wasm-bindgen] diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index caca2a4..61153a9 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_websocket" -version = "0.7.1" +version = "0.7.2" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" @@ -17,8 +17,7 @@ url = "2.2.2" tokio-tungstenite = "0.13.0" [dependencies.rsocket_rust] -version = "0.7.1" -# path = "../rsocket" +version = "0.7" features = ["frame"] [dependencies.tokio] diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index 0d00135..b4ce4d0 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust" -version = "0.7.1" +version = "0.7.2" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" From 20b0adae8310ee06e0c26ece8be92d88fb62b112 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Sun, 12 Dec 2021 22:37:45 +0800 Subject: [PATCH 60/70] feat: support custom websocket request (#52) --- rsocket-transport-websocket/Cargo.toml | 4 +-- rsocket-transport-websocket/src/client.rs | 25 +++++++++++++----- rsocket-transport-websocket/src/lib.rs | 32 ++++++++++++++++++++++- 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index 61153a9..ef50d4b 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_websocket" -version = "0.7.2" +version = "0.7.3" authors = ["Jeffsky "] edition = "2018" license = "Apache-2.0" @@ -23,4 +23,4 @@ features = ["frame"] [dependencies.tokio] version = "1.0.3" default-features = false -features = [ "rt", "rt-multi-thread", "net", "sync"] +features = [ "macros", "rt", "rt-multi-thread", "net", "sync"] diff --git a/rsocket-transport-websocket/src/client.rs b/rsocket-transport-websocket/src/client.rs index 512338b..d97989c 100644 --- a/rsocket-transport-websocket/src/client.rs +++ b/rsocket-transport-websocket/src/client.rs @@ -2,15 +2,18 @@ use std::net::SocketAddr; use rsocket_rust::{async_trait, error::RSocketError, transport::Transport, Result}; use tokio::net::TcpStream; -use tokio_tungstenite::{accept_async, connect_async}; +use tokio_tungstenite::{accept_async, connect_async, tungstenite::handshake::client::Request}; use url::Url; use super::connection::WebsocketConnection; +pub type WebsocketRequest = Request; + #[derive(Debug)] pub(crate) enum Connector { Direct(TcpStream), - Lazy(Url), + Url(Url), + Request(WebsocketRequest), } #[derive(Debug)] @@ -34,7 +37,11 @@ impl Transport for WebsocketClientTransport { Ok(ws) => Ok(WebsocketConnection::new(ws)), Err(e) => Err(RSocketError::Other(e.into()).into()), }, - Connector::Lazy(u) => match connect_async(u).await { + Connector::Url(u) => match connect_async(u).await { + Ok((stream, _)) => Ok(WebsocketConnection::new(stream)), + Err(e) => Err(RSocketError::Other(e.into()).into()), + }, + Connector::Request(req) => match connect_async(req).await { Ok((stream, _)) => Ok(WebsocketConnection::new(stream)), Err(e) => Err(RSocketError::Other(e.into()).into()), }, @@ -55,19 +62,25 @@ impl From<&str> for WebsocketClientTransport { } else { Url::parse(&format!("ws://{}", addr)).unwrap() }; - WebsocketClientTransport::new(Connector::Lazy(u)) + WebsocketClientTransport::new(Connector::Url(u)) } } impl From for WebsocketClientTransport { fn from(addr: SocketAddr) -> WebsocketClientTransport { let u = Url::parse(&format!("ws://{}", addr)).unwrap(); - WebsocketClientTransport::new(Connector::Lazy(u)) + WebsocketClientTransport::new(Connector::Url(u)) } } impl From for WebsocketClientTransport { fn from(url: Url) -> WebsocketClientTransport { - WebsocketClientTransport::new(Connector::Lazy(url)) + WebsocketClientTransport::new(Connector::Url(url)) + } +} + +impl From for WebsocketClientTransport { + fn from(req: WebsocketRequest) -> Self { + WebsocketClientTransport::new(Connector::Request(req)) } } diff --git a/rsocket-transport-websocket/src/lib.rs b/rsocket-transport-websocket/src/lib.rs index 6ad58fc..8c88456 100644 --- a/rsocket-transport-websocket/src/lib.rs +++ b/rsocket-transport-websocket/src/lib.rs @@ -7,5 +7,35 @@ mod client; mod connection; mod server; -pub use client::WebsocketClientTransport; +pub use client::{WebsocketClientTransport, WebsocketRequest}; pub use server::WebsocketServerTransport; + +#[cfg(test)] +mod test_websocket { + use super::*; + use rsocket_rust::prelude::*; + + #[ignore] + #[tokio::test] + async fn test_client() { + let req: WebsocketRequest = WebsocketRequest::builder() + .uri("ws://127.0.0.1:8080/hello") + .header("x-foo-bar", "42") + .method("GET") + .body(()) + .unwrap(); + let tp = WebsocketClientTransport::from(req); + let c = RSocketFactory::connect() + .transport(tp) + .start() + .await + .expect("connect failed"); + let res = c + .request_response(Payload::builder().set_data_utf8("foo").build()) + .await + .expect("request failed") + .unwrap(); + + println!("response: {:?}", res); + } +} From 86196438d535d7e223176dc5bc579701f99f4547 Mon Sep 17 00:00:00 2001 From: Andreas Doerr Date: Wed, 30 Mar 2022 14:01:04 +0200 Subject: [PATCH 61/70] feat: use rust 2021 edition (#54) --- examples/Cargo.toml | 2 +- rsocket-messaging/Cargo.toml | 2 +- rsocket-test/Cargo.toml | 2 +- rsocket-transport-tcp/Cargo.toml | 2 +- rsocket-transport-wasm/Cargo.toml | 2 +- rsocket-transport-websocket/Cargo.toml | 2 +- rsocket/Cargo.toml | 2 +- rustfmt.toml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 935fb91..8cdfbd2 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -2,7 +2,7 @@ name = "examples" version = "0.0.0" authors = ["Jeffsky "] -edition = "2018" +edition = "2021" publish = false [dev-dependencies] diff --git a/rsocket-messaging/Cargo.toml b/rsocket-messaging/Cargo.toml index 8864b15..603349d 100644 --- a/rsocket-messaging/Cargo.toml +++ b/rsocket-messaging/Cargo.toml @@ -2,7 +2,7 @@ name = "rsocket_rust_messaging" version = "0.7.2" authors = ["Jeffsky "] -edition = "2018" +edition = "2021" license = "Apache-2.0" readme = "README.md" repository = "https://github.com/rsocket/rsocket-rust" diff --git a/rsocket-test/Cargo.toml b/rsocket-test/Cargo.toml index dc3f4a1..3b1229a 100644 --- a/rsocket-test/Cargo.toml +++ b/rsocket-test/Cargo.toml @@ -2,7 +2,7 @@ name = "rsocket_rust_test" version = "0.0.0" authors = ["Jeffsky "] -edition = "2018" +edition = "2021" publish = false [dev-dependencies] diff --git a/rsocket-transport-tcp/Cargo.toml b/rsocket-transport-tcp/Cargo.toml index 0dbe4fc..84e2efd 100644 --- a/rsocket-transport-tcp/Cargo.toml +++ b/rsocket-transport-tcp/Cargo.toml @@ -2,7 +2,7 @@ name = "rsocket_rust_transport_tcp" version = "0.7.2" authors = ["Jeffsky "] -edition = "2018" +edition = "2021" license = "Apache-2.0" readme = "README.md" repository = "https://github.com/rsocket/rsocket-rust" diff --git a/rsocket-transport-wasm/Cargo.toml b/rsocket-transport-wasm/Cargo.toml index 991f11e..243775d 100644 --- a/rsocket-transport-wasm/Cargo.toml +++ b/rsocket-transport-wasm/Cargo.toml @@ -2,7 +2,7 @@ name = "rsocket_rust_transport_wasm" version = "0.7.2" authors = ["Jeffsky "] -edition = "2018" +edition = "2021" license = "Apache-2.0" readme = "README.md" repository = "https://github.com/rsocket/rsocket-rust" diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index ef50d4b..7eda3d8 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -2,7 +2,7 @@ name = "rsocket_rust_transport_websocket" version = "0.7.3" authors = ["Jeffsky "] -edition = "2018" +edition = "2021" license = "Apache-2.0" readme = "README.md" repository = "https://github.com/rsocket/rsocket-rust" diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index b4ce4d0..2680d2c 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -2,7 +2,7 @@ name = "rsocket_rust" version = "0.7.2" authors = ["Jeffsky "] -edition = "2018" +edition = "2021" license = "Apache-2.0" readme = "README.md" repository = "https://github.com/rsocket/rsocket-rust" diff --git a/rustfmt.toml b/rustfmt.toml index 5cc1634..ba9b0e4 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,2 +1,2 @@ -edition = "2018" +edition = 2021" group_imports="StdExternalCrate" From 04ffc7023680277c8569c53274061ea5194aa9e6 Mon Sep 17 00:00:00 2001 From: Andreas Doerr Date: Sat, 23 Apr 2022 14:32:04 +0200 Subject: [PATCH 62/70] chore(CI): use dependabot (#56) --- .github/dependabot.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..1b10329 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# Please see the documentation for all configuration options: +# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: +- package-ecosystem: cargo + directory: "/" + schedule: + interval: daily + time: "12:00" + open-pull-requests-limit: 10 From 3e2dbf0213459c13df71f6970bee7848dba76886 Mon Sep 17 00:00:00 2001 From: Andreas Doerr Date: Sat, 23 Apr 2022 14:33:45 +0200 Subject: [PATCH 63/70] chore(lint): make clippy happy (#55) --- rsocket-messaging/src/lib.rs | 2 ++ rsocket-messaging/src/requester.rs | 17 +++------------ rsocket-transport-wasm/src/connection.rs | 2 +- rsocket-transport-wasm/src/lib.rs | 2 ++ rsocket-transport-websocket/src/connection.rs | 2 +- rsocket/src/extension/mime.rs | 5 +---- rsocket/src/lib.rs | 1 + rsocket/src/transport/socket.rs | 21 ++++++++----------- 8 files changed, 20 insertions(+), 32 deletions(-) diff --git a/rsocket-messaging/src/lib.rs b/rsocket-messaging/src/lib.rs index 5b9ec96..7e73a74 100644 --- a/rsocket-messaging/src/lib.rs +++ b/rsocket-messaging/src/lib.rs @@ -1,3 +1,5 @@ +#![allow(clippy::upper_case_acronyms)] + mod misc; mod requester; diff --git a/rsocket-messaging/src/requester.rs b/rsocket-messaging/src/requester.rs index c252d40..bc3bbc8 100644 --- a/rsocket-messaging/src/requester.rs +++ b/rsocket-messaging/src/requester.rs @@ -36,6 +36,7 @@ pub struct RequestSpec { data: Option, } +#[derive(Default)] pub struct RequesterBuilder { data_mime_type: Option, route: Option, @@ -52,18 +53,6 @@ pub struct Unpacker { inner: UnpackerResult, } -impl Default for RequesterBuilder { - fn default() -> Self { - Self { - data_mime_type: None, - route: None, - metadata: Default::default(), - data: None, - tp: None, - } - } -} - impl RequesterBuilder { pub fn data_mime_type(mut self, mime_type: I) -> Self where @@ -371,9 +360,9 @@ where match mime_type.as_u8() { Some(code) => { if code == MimeType::APPLICATION_JSON.as_u8().unwrap() { - Ok(Some(unmarshal(misc::json(), &raw.as_ref())?)) + Ok(Some(unmarshal(misc::json(), raw.as_ref())?)) } else if code == MimeType::APPLICATION_CBOR.as_u8().unwrap() { - Ok(Some(unmarshal(misc::cbor(), &raw.as_ref())?)) + Ok(Some(unmarshal(misc::cbor(), raw.as_ref())?)) } else { Err(RSocketError::WithDescription("unsupported mime type!".into()).into()) } diff --git a/rsocket-transport-wasm/src/connection.rs b/rsocket-transport-wasm/src/connection.rs index bff9d11..a69177c 100644 --- a/rsocket-transport-wasm/src/connection.rs +++ b/rsocket-transport-wasm/src/connection.rs @@ -19,7 +19,7 @@ impl Connection for WebsocketConnection { fn split(self) -> (Box, Box) { ( Box::new(self.tx.sink_map_err(|e| RSocketError::Other(e.into()))), - Box::new(self.rx.map(|it| Ok(it))), + Box::new(self.rx.map(Ok)), ) } } diff --git a/rsocket-transport-wasm/src/lib.rs b/rsocket-transport-wasm/src/lib.rs index cab558a..688b573 100644 --- a/rsocket-transport-wasm/src/lib.rs +++ b/rsocket-transport-wasm/src/lib.rs @@ -1,4 +1,6 @@ #![allow(clippy::type_complexity)] +#![allow(clippy::unused_unit)] +#![allow(clippy::from_over_into)] #[macro_use] extern crate serde_derive; diff --git a/rsocket-transport-websocket/src/connection.rs b/rsocket-transport-websocket/src/connection.rs index ea66d62..a48b9c0 100644 --- a/rsocket-transport-websocket/src/connection.rs +++ b/rsocket-transport-websocket/src/connection.rs @@ -72,7 +72,7 @@ impl Connection for WebsocketConnection { bf.put_slice(&raw[..]); match Frame::decode(&mut bf) { Ok(frame) => Ok(frame), - Err(e) => Err(RSocketError::Other(e.into())), + Err(e) => Err(RSocketError::Other(e)), } } Err(e) => Err(RSocketError::Other(e.into())), diff --git a/rsocket/src/extension/mime.rs b/rsocket/src/extension/mime.rs index 8b0d7d4..cc14c92 100644 --- a/rsocket/src/extension/mime.rs +++ b/rsocket/src/extension/mime.rs @@ -44,10 +44,7 @@ impl MimeType { pub fn as_str(&self) -> Option<&str> { match self { Self::Normal(s) => Some(s.as_ref()), - Self::WellKnown(n) => match U8_TO_STR.get(n) { - Some(v) => Some(v), - None => None, - }, + Self::WellKnown(n) => U8_TO_STR.get(n).copied(), } } } diff --git a/rsocket/src/lib.rs b/rsocket/src/lib.rs index c68a49c..20eb38d 100644 --- a/rsocket/src/lib.rs +++ b/rsocket/src/lib.rs @@ -2,6 +2,7 @@ #![allow(unused_imports)] #![allow(unused_variables)] #![allow(clippy::type_complexity)] +#![allow(clippy::from_over_into)] #![doc(test( no_crate_inject, attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables)) diff --git a/rsocket/src/transport/socket.rs b/rsocket/src/transport/socket.rs index 4a139e8..e11c419 100644 --- a/rsocket/src/transport/socket.rs +++ b/rsocket/src/transport/socket.rs @@ -132,10 +132,9 @@ impl DuplexSocket { .set_code(error::ERR_REJECT_SETUP) .set_data(Bytes::from(errmsg)) .build(); - if let Err(_) = self.tx.send(sending) { + if self.tx.send(sending).is_err() { error!("Reject setup failed"); } - return; } } Body::Resume(v) => { @@ -274,18 +273,18 @@ impl DuplexSocket { let e = RSocketError::must_new_from_code(input.get_code(), desc); match handler { Handler::ReqRR(tx) => { - if let Err(_) = tx.send(Err(e.into())) { + if tx.send(Err(e.into())).is_err() { error!("respond with error for REQUEST_RESPONSE failed!"); } } Handler::ResRR(_) => unreachable!(), Handler::ReqRS(tx) => { - if let Err(_) = tx.send(Err(e.into())).await { + if (tx.send(Err(e.into())).await).is_err() { error!("respond with error for REQUEST_STREAM failed!"); }; } Handler::ReqRC(tx) => { - if let Err(_) = tx.send(Err(e.into())).await { + if (tx.send(Err(e.into())).await).is_err() { error!("respond with error for REQUEST_CHANNEL failed!"); } } @@ -305,7 +304,7 @@ impl DuplexSocket { match handler { Handler::ReqRR(sender) => { info!("REQUEST_RESPONSE {} cancelled!", sid); - if let Err(_) = sender.send(e) { + if sender.send(e).is_err() { error!("notify cancel for REQUEST_RESPONSE failed: sid={}", sid); } } @@ -331,13 +330,11 @@ impl DuplexSocket { Handler::ReqRR(_) => match o.remove() { Handler::ReqRR(sender) => { if flag & Frame::FLAG_NEXT != 0 { - if let Err(_) = sender.send(Ok(Some(input))) { + if sender.send(Ok(Some(input))).is_err() { error!("response successful payload for REQUEST_RESPONSE failed: sid={}",sid); } - } else { - if let Err(_) = sender.send(Ok(None)) { + } else if sender.send(Ok(None)).is_err() { error!("response successful payload for REQUEST_RESPONSE failed: sid={}",sid); - } } } _ => unreachable!(), @@ -364,7 +361,7 @@ impl DuplexSocket { if flag & Frame::FLAG_NEXT != 0 { if sender.is_closed() { self.send_cancel_frame(sid); - } else if let Err(_) = sender.clone().send(Ok(input)).await { + } else if (sender.clone().send(Ok(input)).await).is_err() { error!("response successful payload for REQUEST_CHANNEL failed: sid={}",sid); self.send_cancel_frame(sid); } @@ -439,7 +436,7 @@ impl DuplexSocket { } // async remove canceller - if let Err(_) = canceller.send(sid).await { + if (canceller.send(sid).await).is_err() { error!("Send canceller failed: sid={}", sid); } From 822405fd6afb3e5e5fe05ed469f9151f3e8769a8 Mon Sep 17 00:00:00 2001 From: Andreas Doerr Date: Thu, 23 Jun 2022 06:39:21 +0200 Subject: [PATCH 64/70] Bump `dashmap` to latest version (#57) --- rsocket/Cargo.toml | 4 ++-- rsocket/src/frame/cancel.rs | 2 +- rsocket/src/frame/error.rs | 2 +- rsocket/src/frame/keepalive.rs | 2 +- rsocket/src/frame/lease.rs | 2 +- rsocket/src/frame/metadata_push.rs | 2 +- rsocket/src/frame/mod.rs | 4 ++-- rsocket/src/frame/payload.rs | 2 +- rsocket/src/frame/request_channel.rs | 2 +- rsocket/src/frame/request_fnf.rs | 2 +- rsocket/src/frame/request_n.rs | 2 +- rsocket/src/frame/request_response.rs | 2 +- rsocket/src/frame/request_stream.rs | 2 +- rsocket/src/frame/resume.rs | 2 +- rsocket/src/frame/resume_ok.rs | 2 +- rsocket/src/frame/setup.rs | 2 +- rsocket/src/frame/version.rs | 2 +- 17 files changed, 19 insertions(+), 19 deletions(-) diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index 2680d2c..0855e6f 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust" -version = "0.7.2" +version = "0.7.3" authors = ["Jeffsky "] edition = "2021" license = "Apache-2.0" @@ -15,7 +15,7 @@ bytes = "1.0.1" futures = "0.3.15" once_cell = "1.7.2" async-trait = "0.1.50" -dashmap = "4.0.2" +dashmap = "5.3.4" thiserror = "1.0.24" anyhow = "1.0.40" async-stream = "0.3.1" diff --git a/rsocket/src/frame/cancel.rs b/rsocket/src/frame/cancel.rs index 817fd67..f1bbc94 100644 --- a/rsocket/src/frame/cancel.rs +++ b/rsocket/src/frame/cancel.rs @@ -1,6 +1,6 @@ use super::{Body, Frame}; -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, PartialEq)] pub struct Cancel {} pub struct CancelBuilder { diff --git a/rsocket/src/frame/error.rs b/rsocket/src/frame/error.rs index e9a3c68..37290c7 100644 --- a/rsocket/src/frame/error.rs +++ b/rsocket/src/frame/error.rs @@ -6,7 +6,7 @@ use super::{Body, Frame}; use crate::error::RSocketError; use crate::utils::Writeable; -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, PartialEq)] pub struct Error { code: u32, data: Option, diff --git a/rsocket/src/frame/keepalive.rs b/rsocket/src/frame/keepalive.rs index 82b0e77..18c7dae 100644 --- a/rsocket/src/frame/keepalive.rs +++ b/rsocket/src/frame/keepalive.rs @@ -4,7 +4,7 @@ use super::{Body, Frame}; use crate::error::RSocketError; use crate::utils::Writeable; -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, PartialEq)] pub struct Keepalive { last_received_position: u64, data: Option, diff --git a/rsocket/src/frame/lease.rs b/rsocket/src/frame/lease.rs index a75abb4..e84dc4d 100644 --- a/rsocket/src/frame/lease.rs +++ b/rsocket/src/frame/lease.rs @@ -4,7 +4,7 @@ use super::{Body, Frame}; use crate::error::RSocketError; use crate::utils::Writeable; -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, PartialEq)] pub struct Lease { ttl: u32, number_of_requests: u32, diff --git a/rsocket/src/frame/metadata_push.rs b/rsocket/src/frame/metadata_push.rs index 6cda0f5..9de12e5 100644 --- a/rsocket/src/frame/metadata_push.rs +++ b/rsocket/src/frame/metadata_push.rs @@ -3,7 +3,7 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use super::{Body, Frame}; use crate::utils::Writeable; -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, PartialEq)] pub struct MetadataPush { metadata: Option, } diff --git a/rsocket/src/frame/mod.rs b/rsocket/src/frame/mod.rs index c61752f..8600fe6 100644 --- a/rsocket/src/frame/mod.rs +++ b/rsocket/src/frame/mod.rs @@ -40,7 +40,7 @@ pub const REQUEST_MAX: u32 = 0x7FFF_FFFF; // 2147483647 pub(crate) const LEN_HEADER: usize = 6; -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, PartialEq)] pub enum Body { Setup(Setup), Lease(Lease), @@ -58,7 +58,7 @@ pub enum Body { ResumeOK(ResumeOK), } -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, PartialEq)] pub struct Frame { pub(crate) stream_id: u32, pub(crate) body: Body, diff --git a/rsocket/src/frame/payload.rs b/rsocket/src/frame/payload.rs index 3a06720..8364eed 100644 --- a/rsocket/src/frame/payload.rs +++ b/rsocket/src/frame/payload.rs @@ -5,7 +5,7 @@ use super::{Body, Frame}; use crate::utils::Writeable; use crate::Result; -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, PartialEq)] pub struct Payload { metadata: Option, data: Option, diff --git a/rsocket/src/frame/request_channel.rs b/rsocket/src/frame/request_channel.rs index 9555dcf..15b95d3 100644 --- a/rsocket/src/frame/request_channel.rs +++ b/rsocket/src/frame/request_channel.rs @@ -5,7 +5,7 @@ use super::{Body, Frame, REQUEST_MAX}; use crate::error::RSocketError; use crate::utils::Writeable; -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, PartialEq)] pub struct RequestChannel { initial_request_n: u32, metadata: Option, diff --git a/rsocket/src/frame/request_fnf.rs b/rsocket/src/frame/request_fnf.rs index ed34e68..95a1ad8 100644 --- a/rsocket/src/frame/request_fnf.rs +++ b/rsocket/src/frame/request_fnf.rs @@ -3,7 +3,7 @@ use bytes::{BufMut, Bytes, BytesMut}; use super::{utils, Body, Frame}; use crate::utils::Writeable; -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, PartialEq)] pub struct RequestFNF { metadata: Option, data: Option, diff --git a/rsocket/src/frame/request_n.rs b/rsocket/src/frame/request_n.rs index 4d557e2..d826443 100644 --- a/rsocket/src/frame/request_n.rs +++ b/rsocket/src/frame/request_n.rs @@ -4,7 +4,7 @@ use super::{utils, Body, Frame, REQUEST_MAX}; use crate::error::RSocketError; use crate::utils::Writeable; -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, PartialEq)] pub struct RequestN { n: u32, } diff --git a/rsocket/src/frame/request_response.rs b/rsocket/src/frame/request_response.rs index 5f120cf..510ba2a 100644 --- a/rsocket/src/frame/request_response.rs +++ b/rsocket/src/frame/request_response.rs @@ -3,7 +3,7 @@ use bytes::{BufMut, Bytes, BytesMut}; use super::{utils, Body, Frame}; use crate::utils::Writeable; -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, PartialEq)] pub struct RequestResponse { metadata: Option, data: Option, diff --git a/rsocket/src/frame/request_stream.rs b/rsocket/src/frame/request_stream.rs index 254b86c..12cec2b 100644 --- a/rsocket/src/frame/request_stream.rs +++ b/rsocket/src/frame/request_stream.rs @@ -4,7 +4,7 @@ use super::{utils, Body, Frame, REQUEST_MAX}; use crate::error::RSocketError; use crate::utils::Writeable; -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, PartialEq)] pub struct RequestStream { initial_request_n: u32, metadata: Option, diff --git a/rsocket/src/frame/resume.rs b/rsocket/src/frame/resume.rs index 934c086..4b91fe3 100644 --- a/rsocket/src/frame/resume.rs +++ b/rsocket/src/frame/resume.rs @@ -4,7 +4,7 @@ use super::{Body, Frame, Version}; use crate::error::RSocketError; use crate::utils::Writeable; -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, PartialEq)] pub struct Resume { version: Version, token: Option, diff --git a/rsocket/src/frame/resume_ok.rs b/rsocket/src/frame/resume_ok.rs index 0e53fec..49259d4 100644 --- a/rsocket/src/frame/resume_ok.rs +++ b/rsocket/src/frame/resume_ok.rs @@ -4,7 +4,7 @@ use super::{Body, Frame}; use crate::error::RSocketError; use crate::utils::Writeable; -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, PartialEq)] pub struct ResumeOK { position: u64, } diff --git a/rsocket/src/frame/setup.rs b/rsocket/src/frame/setup.rs index c4f880a..ab403ed 100644 --- a/rsocket/src/frame/setup.rs +++ b/rsocket/src/frame/setup.rs @@ -7,7 +7,7 @@ use super::{Body, Frame, Version}; use crate::error::RSocketError; use crate::utils::{Writeable, DEFAULT_MIME_TYPE}; -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, PartialEq)] pub struct Setup { version: Version, keepalive: u32, diff --git a/rsocket/src/frame/version.rs b/rsocket/src/frame/version.rs index 8f090a5..e6501bd 100644 --- a/rsocket/src/frame/version.rs +++ b/rsocket/src/frame/version.rs @@ -2,7 +2,7 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use crate::utils::Writeable; -#[derive(Debug, Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, Eq, PartialEq)] pub struct Version { major: u16, minor: u16, From 5679665caabb23760e5c8c93b607e18cbb391fa0 Mon Sep 17 00:00:00 2001 From: HouYe Hua Date: Fri, 26 May 2023 13:36:53 +0800 Subject: [PATCH 65/70] correct rsocket_rust dependencies path (#59) --- rsocket-messaging/Cargo.toml | 3 +++ rsocket-test/Cargo.toml | 4 ++++ rsocket-transport-tcp/Cargo.toml | 1 + rsocket-transport-wasm/Cargo.toml | 1 + rsocket-transport-websocket/Cargo.toml | 1 + 5 files changed, 10 insertions(+) diff --git a/rsocket-messaging/Cargo.toml b/rsocket-messaging/Cargo.toml index 603349d..701d103 100644 --- a/rsocket-messaging/Cargo.toml +++ b/rsocket-messaging/Cargo.toml @@ -19,11 +19,14 @@ hex = "0.4.2" url = "2.2.0" [dependencies.rsocket_rust] +path = "../rsocket" version = "0.7" features = ["frame"] [dependencies.rsocket_rust_transport_tcp] +path = "../rsocket-transport-tcp" version = "0.7" [dependencies.rsocket_rust_transport_websocket] +path = "../rsocket-transport-websocket" version = "0.7" diff --git a/rsocket-test/Cargo.toml b/rsocket-test/Cargo.toml index 3b1229a..4a5750c 100644 --- a/rsocket-test/Cargo.toml +++ b/rsocket-test/Cargo.toml @@ -16,16 +16,20 @@ serde = "1.0.126" serde_derive = "1.0.126" [dev-dependencies.rsocket_rust] +path = "../rsocket" version = "0.7" features = ["frame"] [dev-dependencies.rsocket_rust_transport_tcp] +path = "../rsocket-transport-tcp" version = "0.7" [dev-dependencies.rsocket_rust_transport_websocket] +path = "../rsocket-transport-websocket" version = "0.7" [dev-dependencies.rsocket_rust_messaging] +path = "../rsocket-messaging" version = "0.7" [dev-dependencies.tokio] diff --git a/rsocket-transport-tcp/Cargo.toml b/rsocket-transport-tcp/Cargo.toml index 84e2efd..bc75e02 100644 --- a/rsocket-transport-tcp/Cargo.toml +++ b/rsocket-transport-tcp/Cargo.toml @@ -20,6 +20,7 @@ bytes = "1.0.1" cfg-if = "1.0.0" [dependencies.rsocket_rust] +path = "../rsocket" version = "0.7" features = ["frame"] diff --git a/rsocket-transport-wasm/Cargo.toml b/rsocket-transport-wasm/Cargo.toml index 243775d..d9eab2c 100644 --- a/rsocket-transport-wasm/Cargo.toml +++ b/rsocket-transport-wasm/Cargo.toml @@ -20,6 +20,7 @@ serde_derive = "1.0.126" log = "0.4.14" [dependencies.rsocket_rust] +path = "../rsocket" version = "0.7" features = ["frame"] diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index 7eda3d8..1198c4e 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -17,6 +17,7 @@ url = "2.2.2" tokio-tungstenite = "0.13.0" [dependencies.rsocket_rust] +path = "../rsocket" version = "0.7" features = ["frame"] From aea41bde71ca0248779ca9fa2e579f91ea28b017 Mon Sep 17 00:00:00 2001 From: hplewis Date: Wed, 31 May 2023 04:54:38 -0700 Subject: [PATCH 66/70] feat: add support for wss (TLS) connections for clients (#62) * Add tls support for websocket client transport * Update websocket client example for headers --- rsocket-transport-websocket/Cargo.toml | 5 ++++- rsocket-transport-websocket/src/client.rs | 21 +++++++++++++------ rsocket-transport-websocket/src/connection.rs | 7 ++++--- rsocket-transport-websocket/src/lib.rs | 13 ++++++------ 4 files changed, 30 insertions(+), 16 deletions(-) diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index 1198c4e..43b621d 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -14,7 +14,10 @@ log = "0.4.14" futures = "0.3.15" bytes = "1.0.1" url = "2.2.2" -tokio-tungstenite = "0.13.0" + +[dependencies.tokio-tungstenite] +version = "0.18.0" +features = ["native-tls"] [dependencies.rsocket_rust] path = "../rsocket" diff --git a/rsocket-transport-websocket/src/client.rs b/rsocket-transport-websocket/src/client.rs index d97989c..03d4cfc 100644 --- a/rsocket-transport-websocket/src/client.rs +++ b/rsocket-transport-websocket/src/client.rs @@ -2,16 +2,19 @@ use std::net::SocketAddr; use rsocket_rust::{async_trait, error::RSocketError, transport::Transport, Result}; use tokio::net::TcpStream; -use tokio_tungstenite::{accept_async, connect_async, tungstenite::handshake::client::Request}; +use tokio_tungstenite::{accept_async, connect_async, tungstenite::handshake::client::Request, MaybeTlsStream}; use url::Url; use super::connection::WebsocketConnection; pub type WebsocketRequest = Request; +const WS_PROTO: &str = "ws://"; +const WSS_PROTO: &str = "wss://"; + #[derive(Debug)] pub(crate) enum Connector { - Direct(TcpStream), + Direct(MaybeTlsStream), Url(Url), Request(WebsocketRequest), } @@ -49,18 +52,24 @@ impl Transport for WebsocketClientTransport { } } +impl From> for WebsocketClientTransport { + fn from(socket: MaybeTlsStream) -> WebsocketClientTransport { + WebsocketClientTransport::new(Connector::Direct(socket)) + } +} + impl From for WebsocketClientTransport { fn from(socket: TcpStream) -> WebsocketClientTransport { - WebsocketClientTransport::new(Connector::Direct(socket)) + WebsocketClientTransport::new(Connector::Direct(MaybeTlsStream::Plain(socket))) } } impl From<&str> for WebsocketClientTransport { fn from(addr: &str) -> WebsocketClientTransport { - let u = if addr.starts_with("ws://") { + let u = if addr.starts_with(WS_PROTO) || addr.starts_with(WSS_PROTO) { Url::parse(addr).unwrap() } else { - Url::parse(&format!("ws://{}", addr)).unwrap() + Url::parse(&format!("{}{}", WS_PROTO, addr)).unwrap() }; WebsocketClientTransport::new(Connector::Url(u)) } @@ -68,7 +77,7 @@ impl From<&str> for WebsocketClientTransport { impl From for WebsocketClientTransport { fn from(addr: SocketAddr) -> WebsocketClientTransport { - let u = Url::parse(&format!("ws://{}", addr)).unwrap(); + let u = Url::parse(&format!("{}{}", WS_PROTO, addr)).unwrap(); WebsocketClientTransport::new(Connector::Url(u)) } } diff --git a/rsocket-transport-websocket/src/connection.rs b/rsocket-transport-websocket/src/connection.rs index a48b9c0..7217ca2 100644 --- a/rsocket-transport-websocket/src/connection.rs +++ b/rsocket-transport-websocket/src/connection.rs @@ -10,6 +10,7 @@ use rsocket_rust::{ utils::Writeable, }; use tokio::net::TcpStream; +use tokio_tungstenite::MaybeTlsStream; use tokio_tungstenite::{ tungstenite::{Error as WsError, Message}, WebSocketStream, @@ -17,16 +18,16 @@ use tokio_tungstenite::{ #[derive(Debug)] pub struct WebsocketConnection { - stream: WebSocketStream, + stream: WebSocketStream>, } impl WebsocketConnection { - pub(crate) fn new(stream: WebSocketStream) -> WebsocketConnection { + pub(crate) fn new(stream: WebSocketStream>) -> WebsocketConnection { WebsocketConnection { stream } } } -struct InnerSink(SplitSink, Message>); +struct InnerSink(SplitSink>, Message>); impl Sink for InnerSink { type Error = WsError; diff --git a/rsocket-transport-websocket/src/lib.rs b/rsocket-transport-websocket/src/lib.rs index 8c88456..4a34f09 100644 --- a/rsocket-transport-websocket/src/lib.rs +++ b/rsocket-transport-websocket/src/lib.rs @@ -14,16 +14,17 @@ pub use server::WebsocketServerTransport; mod test_websocket { use super::*; use rsocket_rust::prelude::*; + use tokio_tungstenite::tungstenite::client::IntoClientRequest; #[ignore] #[tokio::test] async fn test_client() { - let req: WebsocketRequest = WebsocketRequest::builder() - .uri("ws://127.0.0.1:8080/hello") - .header("x-foo-bar", "42") - .method("GET") - .body(()) - .unwrap(); + let mut req = "ws://127.0.0.1:8080/hello".into_client_request().unwrap(); + + // Optional: custom headers + let headers = req.headers_mut(); + headers.insert("x-foo-bar", "42".parse().unwrap()); + let tp = WebsocketClientTransport::from(req); let c = RSocketFactory::connect() .transport(tp) From f414ef4f9d3cf5692e4e231e01f58fc1374725a4 Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Wed, 31 May 2023 21:14:27 +0800 Subject: [PATCH 67/70] chore(release): prepare for v0.7.3 (#63) --- .chglog/CHANGELOG.tpl.md | 30 ---- .chglog/config.yml | 28 --- .github/workflows/linelint.yml | 31 ++++ .linelint.yml | 18 ++ .pre-commit-config.yaml | 32 ++++ CHANGELOG.md | 166 +++++++----------- README.md | 6 +- cliff.toml | 75 ++++++++ justfile | 2 +- rsocket-messaging/Cargo.toml | 2 +- .../tests/test_stream_cancellation.rs | 98 +++++++---- rsocket-transport-tcp/Cargo.toml | 2 +- rsocket-transport-wasm/Cargo.toml | 2 +- rsocket-transport-websocket/src/client.rs | 4 +- rsocket-transport-websocket/src/lib.rs | 3 +- rsocket/README.md | 1 - rsocket/src/transport/socket.rs | 16 +- rustfmt.toml | 3 +- 18 files changed, 300 insertions(+), 219 deletions(-) delete mode 100755 .chglog/CHANGELOG.tpl.md delete mode 100755 .chglog/config.yml create mode 100644 .github/workflows/linelint.yml create mode 100644 .linelint.yml create mode 100644 .pre-commit-config.yaml create mode 100644 cliff.toml diff --git a/.chglog/CHANGELOG.tpl.md b/.chglog/CHANGELOG.tpl.md deleted file mode 100755 index 63ce69b..0000000 --- a/.chglog/CHANGELOG.tpl.md +++ /dev/null @@ -1,30 +0,0 @@ -{{ range .Versions }} - -## {{ if .Tag.Previous }}[{{ .Tag.Name }}]({{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }}){{ else }}{{ .Tag.Name }}{{ end }} ({{ datetime "2006-01-02" .Tag.Date }}) - -{{ range .CommitGroups -}} -### {{ .Title }} - -{{ range .Commits -}} -* {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }} -{{ end }} -{{ end -}} - -{{- if .MergeCommits -}} -### Pull Requests - -{{ range .MergeCommits -}} -* {{ .Header }} -{{ end }} -{{ end -}} - -{{- if .NoteGroups -}} -{{ range .NoteGroups -}} -### {{ .Title }} - -{{ range .Notes }} -{{ .Body }} -{{ end }} -{{ end -}} -{{ end -}} -{{ end -}} \ No newline at end of file diff --git a/.chglog/config.yml b/.chglog/config.yml deleted file mode 100755 index dc64da1..0000000 --- a/.chglog/config.yml +++ /dev/null @@ -1,28 +0,0 @@ -style: github -template: CHANGELOG.tpl.md -info: - title: CHANGELOG - repository_url: https://github.com/rsocket/rsocket-rust -options: - commits: - # filters: - # Type: - # - feat - # - fix - # - perf - # - refactor - commit_groups: - # title_maps: - # feat: Features - # fix: Bug Fixes - # perf: Performance Improvements - # refactor: Code Refactoring - header: - pattern: "^(\\w*)(?:\\(([\\w\\$\\.\\-\\*\\s]*)\\))?\\:\\s(.*)$" - pattern_maps: - - Type - - Scope - - Subject - notes: - keywords: - - BREAKING CHANGE \ No newline at end of file diff --git a/.github/workflows/linelint.yml b/.github/workflows/linelint.yml new file mode 100644 index 0000000..eb467ef --- /dev/null +++ b/.github/workflows/linelint.yml @@ -0,0 +1,31 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +name: linelint +on: [push, pull_request] + +jobs: + linelint: + runs-on: ubuntu-latest + name: Check if all files end in newline + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Linelint + uses: fernandrone/linelint@0.0.4 diff --git a/.linelint.yml b/.linelint.yml new file mode 100644 index 0000000..8188b67 --- /dev/null +++ b/.linelint.yml @@ -0,0 +1,18 @@ +# 'true' will fix files +autofix: true + +# list of paths to ignore, uses gitignore syntaxes (executes before any rule) +ignore: + - .git/ + +rules: + # checks if file ends in a newline character + end-of-file: + # set to true to enable this rule + enable: true + + # set to true to disable autofix (if enabled globally) + disable-autofix: false + + # if true also checks if file ends in a single newline character + single-new-line: true diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..530c034 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,32 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.3.0 + hooks: + - id: end-of-file-fixer + - id: trailing-whitespace + - repo: https://github.com/doublify/pre-commit-rust + rev: v1.0 + hooks: + - id: fmt + - id: cargo-check + - id: clippy diff --git a/CHANGELOG.md b/CHANGELOG.md index 07213a6..0a38199 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,140 +1,94 @@ +# Changelog - -## [v0.7.0](https://github.com/rsocket/rsocket-rust/compare/v0.6.0...v0.7.0) (2021-01-14) +All notable changes to this project will be documented in this file. -### Chore +## [unreleased] -* update deps ([#42](https://github.com/rsocket/rsocket-rust/issues/42)) -* config chglog ([#41](https://github.com/rsocket/rsocket-rust/issues/41)) -* use mkcert to generate TLS example certificates and keys ([#38](https://github.com/rsocket/rsocket-rust/issues/38)) -* add RSocket trait example in readme -* fix readme -* bump tokio to v0.3.6 -* **rustfmt:** optimize import ([#39](https://github.com/rsocket/rsocket-rust/issues/39)) +### Features -### Feat +- Support custom websocket request (#52) +- Use rust 2021 edition (#54) +- Add support for wss (TLS) connections for clients (#62) -* close connection correctly when client is dropped ([#40](https://github.com/rsocket/rsocket-rust/issues/40)) -* migrate to tokio v1 -* change transport api ([#35](https://github.com/rsocket/rsocket-rust/issues/35)) -* implment tls transport ([#31](https://github.com/rsocket/rsocket-rust/issues/31)) -* redesign RSocket trait based on async_trait -* **request_response:** handle empty response correctly +### Miscellaneous Tasks -### Fix +- Use dependabot (#56) +- Make clippy happy (#55) -* register client-side responder correctly ([#36](https://github.com/rsocket/rsocket-rust/issues/36)) -* simplify Option convert -* remove useless examples +## [0.7.2] - 2021-09-01 +### Bug Fixes - -## [v0.6.0](https://github.com/rsocket/rsocket-rust/compare/v0.5.3...v0.6.0) (2020-12-13) +- Check send error -### Chore +### Features -* prelease 0.6 -* upgrade deps -* use gh actions instead of travis ([#22](https://github.com/rsocket/rsocket-rust/issues/22)) +- Use cfg_if and once_cell +- Add some macros +- Implemented cancel frame handling (#49) -### Feat +### Miscellaneous Tasks -* implement client-side keepalive ([#25](https://github.com/rsocket/rsocket-rust/issues/25)) -* support tokio v0.3.x ([#23](https://github.com/rsocket/rsocket-rust/issues/23)) +- Upgrade version to 0.7.1 +- Update examples +- Upgrade deps +- Update dependencies for readme (#46) +- Update example code in readme (#47) +- Upgrade to 0.7.2 (#50) -### Fix +## [0.7.0] - 2021-01-14 -* convert bytes to utf8 safely ([#27](https://github.com/rsocket/rsocket-rust/issues/27)) -* optimize bytes write action ([#24](https://github.com/rsocket/rsocket-rust/issues/24)) +### Bug Fixes -### Refactor - -* use thiserror & anyhow as error struct ([#20](https://github.com/rsocket/rsocket-rust/issues/20)) - -### Pull Requests - -* Merge pull request [#19](https://github.com/rsocket/rsocket-rust/issues/19) from rsocket/develop - - - -## [v0.5.3](https://github.com/rsocket/rsocket-rust/compare/v0.5.2...v0.5.3) (2020-06-11) - -### Pull Requests - -* Merge pull request [#17](https://github.com/rsocket/rsocket-rust/issues/17) from rsocket/develop -* Merge pull request [#16](https://github.com/rsocket/rsocket-rust/issues/16) from seal90/develop +- Remove useless examples +- Simplify Option convert +- Register client-side responder correctly (#36) +### Features - -## [v0.5.2](https://github.com/rsocket/rsocket-rust/compare/v0.5.1...v0.5.2) (2020-05-26) +- Redesign RSocket trait based on async_trait +- Handle empty response correctly +- Implment tls transport (#31) +- Change transport api (#35) +- Migrate to tokio v1 +- Close connection correctly when client is dropped (#40) -### Pull Requests +### Miscellaneous Tasks -* Merge pull request [#14](https://github.com/rsocket/rsocket-rust/issues/14) from rsocket/feature/messaging -* Merge pull request [#11](https://github.com/rsocket/rsocket-rust/issues/11) from kuronyago/feature/wasm_fire_and_forget -* Merge pull request [#9](https://github.com/rsocket/rsocket-rust/issues/9) from kuronyago/docs/readme_for_websocket_example +- Bump tokio to v0.3.6 +- Fix readme +- Add RSocket trait example in readme +- Use mkcert to generate TLS example certificates and keys (#38) +- Optimize import (#39) +- Config chglog (#41) +- Update deps (#42) +## [0.6.0] - 2020-12-13 - -## [v0.5.1](https://github.com/rsocket/rsocket-rust/compare/v0.5.0...v0.5.1) (2020-04-06) +### Bug Fixes -### Pull Requests +- Optimize bytes write action (#24) +- Convert bytes to utf8 safely (#27) -* Merge pull request [#8](https://github.com/rsocket/rsocket-rust/issues/8) from rsocket/develop +### Features +- Support tokio v0.3.x (#23) +- Implement client-side keepalive (#25) - -## [v0.5.0](https://github.com/rsocket/rsocket-rust/compare/v0.4.0...v0.5.0) (2020-02-22) +### Miscellaneous Tasks -### Pull Requests +- Use gh actions instead of travis (#22) +- Upgrade deps +- Prelease 0.6 -* Merge pull request [#6](https://github.com/rsocket/rsocket-rust/issues/6) from rsocket/improve/pick_transport +### Refactor +- Use thiserror & anyhow as error struct (#20) - -## [v0.4.0](https://github.com/rsocket/rsocket-rust/compare/v0.3.0...v0.4.0) (2019-12-24) +## [0.4.0] - 2019-12-24 ### Bugfix -* response payload of REQUEST_RESPONSE will be sent with NEXT|COMPLETE flag. - -### Pull Requests - -* Merge pull request [#4](https://github.com/rsocket/rsocket-rust/issues/4) from rsocket/develop - - - -## [v0.3.0](https://github.com/rsocket/rsocket-rust/compare/v0.2.0...v0.3.0) (2019-12-04) - -### Pull Requests - -* Merge pull request [#3](https://github.com/rsocket/rsocket-rust/issues/3) from rsocket/feature/routing_metadata - - - -## [v0.2.0](https://github.com/rsocket/rsocket-rust/compare/v0.1.5...v0.2.0) (2019-11-29) - -### Pull Requests - -* Merge pull request [#2](https://github.com/rsocket/rsocket-rust/issues/2) from rsocket/feature/async_await - - - -## [v0.1.5](https://github.com/rsocket/rsocket-rust/compare/v0.1.4...v0.1.5) (2019-10-08) - - - -## [v0.1.4](https://github.com/rsocket/rsocket-rust/compare/v0.1.3...v0.1.4) (2019-09-06) - - - -## [v0.1.3](https://github.com/rsocket/rsocket-rust/compare/v0.1.2...v0.1.3) (2019-09-03) - - - -## [v0.1.2](https://github.com/rsocket/rsocket-rust/compare/v0.1.0...v0.1.2) (2019-09-02) - - - -## v0.1.0 (2019-08-29) +- Response payload of REQUEST_RESPONSE will be sent with NEXT|COMPLETE flag. + diff --git a/README.md b/README.md index a9af911..fa6361f 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,11 @@ Add dependencies in your `Cargo.toml`. ```toml [dependencies] tokio = "1.0.3" -rsocket_rust = "0.7.2" +rsocket_rust = "0.7.3" # add transport dependencies: -# rsocket_rust_transport_tcp = "0.7.2" -# rsocket_rust_transport_websocket = "0.7.2" +# rsocket_rust_transport_tcp = "0.7.3" +# rsocket_rust_transport_websocket = "0.7.3" ``` ### Server diff --git a/cliff.toml b/cliff.toml new file mode 100644 index 0000000..0a88218 --- /dev/null +++ b/cliff.toml @@ -0,0 +1,75 @@ +# git-cliff ~ default configuration file +# https://git-cliff.org/docs/configuration +# +# Lines starting with "#" are comments. +# Configuration options are organized into tables and keys. +# See documentation for more information on available options. + +[changelog] +# changelog header +header = """ +# Changelog\n +All notable changes to this project will be documented in this file.\n +""" +# template for the changelog body +# https://tera.netlify.app/docs +body = """ +{% if version %}\ + ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} +{% else %}\ + ## [unreleased] +{% endif %}\ +{% for group, commits in commits | group_by(attribute="group") %} + ### {{ group | upper_first }} + {% for commit in commits %} + - {% if commit.breaking %}[**breaking**] {% endif %}{{ commit.message | upper_first }}\ + {% endfor %} +{% endfor %}\n +""" +# remove the leading and trailing whitespace from the template +trim = true +# changelog footer +footer = """ + +""" + +[git] +# parse the commits based on https://www.conventionalcommits.org +conventional_commits = true +# filter out the commits that are not conventional +filter_unconventional = true +# process each line of a commit as an individual commit +split_commits = false +# regex for preprocessing the commit messages +commit_preprocessors = [ + # { pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](https://github.com/orhun/git-cliff/issues/${2}))"}, # replace issue numbers +] +# regex for parsing and grouping commits +commit_parsers = [ + { message = "^feat", group = "Features" }, + { message = "^fix", group = "Bug Fixes" }, + { message = "^doc", group = "Documentation" }, + { message = "^perf", group = "Performance" }, + { message = "^refactor", group = "Refactor" }, + { message = "^style", group = "Styling" }, + { message = "^test", group = "Testing" }, + { message = "^chore\\(release\\): prepare for", skip = true }, + { message = "^chore", group = "Miscellaneous Tasks" }, + { body = ".*security", group = "Security" }, +] +# protect breaking changes from being skipped due to matching a skipping commit_parser +protect_breaking_commits = false +# filter out the commits that are not matched by commit parsers +filter_commits = false +# glob pattern for matching git tags +tag_pattern = "v[0-9]*" +# regex for skipping tags +skip_tags = "v0.1.0-beta.1" +# regex for ignoring tags +ignore_tags = "" +# sort the tags topologically +topo_order = false +# sort the commits inside sections by oldest/newest order +sort_commits = "oldest" +# limit the number of commits included in the changelog. +# limit_commits = 42 diff --git a/justfile b/justfile index 5fceac2..8d3b02e 100644 --- a/justfile +++ b/justfile @@ -9,7 +9,7 @@ test: lint: @cargo clippy fmt: - @cargo +nightly fmt + @cargo fmt echo: @RUST_LOG=release cargo run --release --example echo -- serve tcp://127.0.0.1:7878 bench: diff --git a/rsocket-messaging/Cargo.toml b/rsocket-messaging/Cargo.toml index 701d103..7edb572 100644 --- a/rsocket-messaging/Cargo.toml +++ b/rsocket-messaging/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_messaging" -version = "0.7.2" +version = "0.7.3" authors = ["Jeffsky "] edition = "2021" license = "Apache-2.0" diff --git a/rsocket-test/tests/test_stream_cancellation.rs b/rsocket-test/tests/test_stream_cancellation.rs index 08a8bad..52bf373 100644 --- a/rsocket-test/tests/test_stream_cancellation.rs +++ b/rsocket-test/tests/test_stream_cancellation.rs @@ -8,23 +8,24 @@ use std::time::Duration; use anyhow::Result; use async_trait::async_trait; use futures::StreamExt; -use tokio_stream::wrappers::ReceiverStream; - use rsocket_rust::prelude::{Flux, Payload, RSocket}; +use tokio_stream::wrappers::ReceiverStream; #[cfg(test)] mod tests { use std::time::Duration; + use async_stream::stream; use futures::Future; + use rsocket_rust::prelude::*; + use rsocket_rust::utils::EchoRSocket; + use rsocket_rust::Client; + use rsocket_rust_transport_tcp::{ + TcpClientTransport, TcpServerTransport, UnixClientTransport, UnixServerTransport, + }; use rsocket_rust_transport_websocket::{WebsocketClientTransport, WebsocketServerTransport}; use serial_test::serial; use tokio::runtime::Runtime; - use async_stream::stream; - use rsocket_rust::Client; - use rsocket_rust::prelude::*; - use rsocket_rust::utils::EchoRSocket; - use rsocket_rust_transport_tcp::{TcpClientTransport, TcpServerTransport, UnixClientTransport, UnixServerTransport}; use crate::TestSocket; @@ -59,7 +60,12 @@ mod tests { /// When request_stream handle is dropped: 0 subscribers async fn request_stream_can_be_cancelled_by_client(client: Client) { assert_eq!( - client.request_response(Payload::from("subscribers")).await.unwrap().unwrap().data_utf8(), + client + .request_response(Payload::from("subscribers")) + .await + .unwrap() + .unwrap() + .data_utf8(), Some("0") ); @@ -69,7 +75,12 @@ mod tests { assert_eq!(payload.data_utf8(), Some("0")); assert_eq!( - client.request_response(Payload::from("subscribers")).await.unwrap().unwrap().data_utf8(), + client + .request_response(Payload::from("subscribers")) + .await + .unwrap() + .unwrap() + .data_utf8(), Some("1") ); @@ -79,7 +90,12 @@ mod tests { tokio::time::sleep(Duration::from_millis(250)).await; assert_eq!( - client.request_response(Payload::from("subscribers")).await.unwrap().unwrap().data_utf8(), + client + .request_response(Payload::from("subscribers")) + .await + .unwrap() + .unwrap() + .data_utf8(), Some("0") ); } @@ -115,19 +131,27 @@ mod tests { /// When request_channel handle is dropped: 0 subscribers async fn request_channel_can_be_cancelled_by_client(client: Client) { assert_eq!( - client.request_response(Payload::from("subscribers")).await.unwrap().unwrap().data_utf8(), + client + .request_response(Payload::from("subscribers")) + .await + .unwrap() + .unwrap() + .data_utf8(), Some("0") ); - let mut results = client.request_channel( - stream!{ yield Ok(Payload::from("")) }.boxed() - ); + let mut results = client.request_channel(stream! { yield Ok(Payload::from("")) }.boxed()); let payload = results.next().await.expect("valid payload").unwrap(); assert_eq!(payload.metadata_utf8(), Some("subscribers: 1")); assert_eq!(payload.data_utf8(), Some("0")); assert_eq!( - client.request_response(Payload::from("subscribers")).await.unwrap().unwrap().data_utf8(), + client + .request_response(Payload::from("subscribers")) + .await + .unwrap() + .unwrap() + .data_utf8(), Some("1") ); @@ -137,7 +161,12 @@ mod tests { tokio::time::sleep(Duration::from_millis(250)).await; assert_eq!( - client.request_response(Payload::from("subscribers")).await.unwrap().unwrap().data_utf8(), + client + .request_response(Payload::from("subscribers")) + .await + .unwrap() + .unwrap() + .data_utf8(), Some("0") ); } @@ -153,17 +182,19 @@ mod tests { /// Executes the [run_test] scenario using a client which is connected over a UDS transport to /// a TestSocket fn with_uds_test_socket_run(run_test: F) - where - F: (FnOnce(Client) -> Fut) + Send + 'static, - Fut: Future + Send + 'static, + where + F: (FnOnce(Client) -> Fut) + Send + 'static, + Fut: Future + Send + 'static, { info!("=====> begin uds"); let server_runtime = Runtime::new().unwrap(); server_runtime.spawn(async move { RSocketFactory::receive() - .transport(UnixServerTransport::from("/tmp/rsocket-uds.sock".to_owned())) - .acceptor(Box::new(|_setup, _socket| { Ok(Box::new(TestSocket::new())) })) + .transport(UnixServerTransport::from( + "/tmp/rsocket-uds.sock".to_owned(), + )) + .acceptor(Box::new(|_setup, _socket| Ok(Box::new(TestSocket::new())))) .serve() .await }); @@ -175,7 +206,9 @@ mod tests { client_runtime.block_on(async { let client = RSocketFactory::connect() .acceptor(Box::new(|| Box::new(EchoRSocket))) - .transport(UnixClientTransport::from("/tmp/rsocket-uds.sock".to_owned())) + .transport(UnixClientTransport::from( + "/tmp/rsocket-uds.sock".to_owned(), + )) .setup(Payload::from("READY!")) .mime_type("text/plain", "text/plain") .start() @@ -189,16 +222,16 @@ mod tests { /// Executes the [run_test] scenario using a client which is connected over a UDS transport to /// a TestSocket fn with_ws_test_socket_run(run_test: F) - where - F: (FnOnce(Client) -> Fut) + Send + 'static, - Fut: Future + Send + 'static, + where + F: (FnOnce(Client) -> Fut) + Send + 'static, + Fut: Future + Send + 'static, { info!("=====> begin ws"); let server_runtime = Runtime::new().unwrap(); server_runtime.spawn(async move { RSocketFactory::receive() .transport(WebsocketServerTransport::from("127.0.0.1:8080".to_owned())) - .acceptor(Box::new(|_setup, _socket| { Ok(Box::new(TestSocket::new())) })) + .acceptor(Box::new(|_setup, _socket| Ok(Box::new(TestSocket::new())))) .serve() .await }); @@ -217,7 +250,6 @@ mod tests { .await .unwrap(); - run_test(client).await; }); info!("<===== ws done!"); @@ -226,16 +258,16 @@ mod tests { /// Executes the [run_test] scenario using a client which is connected over a TCP transport to /// a TestSocket fn with_tcp_test_socket_run(run_test: F) - where - F: (FnOnce(Client) -> Fut) + Send + 'static, - Fut: Future + Send + 'static, + where + F: (FnOnce(Client) -> Fut) + Send + 'static, + Fut: Future + Send + 'static, { info!("=====> begin tcp"); let server_runtime = Runtime::new().unwrap(); server_runtime.spawn(async move { RSocketFactory::receive() .transport(TcpServerTransport::from("127.0.0.1:7878".to_owned())) - .acceptor(Box::new(|_setup, _socket| { Ok(Box::new(TestSocket::new())) })) + .acceptor(Box::new(|_setup, _socket| Ok(Box::new(TestSocket::new())))) .serve() .await }); @@ -316,7 +348,9 @@ impl RSocket for TestSocket { } let payload = Payload::builder() .set_data_utf8(format!("{}", i).as_str()) - .set_metadata_utf8(format!("subscribers: {}", *subscribers.lock().unwrap()).as_str()) + .set_metadata_utf8( + format!("subscribers: {}", *subscribers.lock().unwrap()).as_str(), + ) .build(); tx.send(Ok(payload)).await.unwrap(); tokio::time::sleep(Duration::from_millis(50)).await; diff --git a/rsocket-transport-tcp/Cargo.toml b/rsocket-transport-tcp/Cargo.toml index bc75e02..d24a243 100644 --- a/rsocket-transport-tcp/Cargo.toml +++ b/rsocket-transport-tcp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_tcp" -version = "0.7.2" +version = "0.7.3" authors = ["Jeffsky "] edition = "2021" license = "Apache-2.0" diff --git a/rsocket-transport-wasm/Cargo.toml b/rsocket-transport-wasm/Cargo.toml index d9eab2c..fa51ed9 100644 --- a/rsocket-transport-wasm/Cargo.toml +++ b/rsocket-transport-wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_wasm" -version = "0.7.2" +version = "0.7.3" authors = ["Jeffsky "] edition = "2021" license = "Apache-2.0" diff --git a/rsocket-transport-websocket/src/client.rs b/rsocket-transport-websocket/src/client.rs index 03d4cfc..400be49 100644 --- a/rsocket-transport-websocket/src/client.rs +++ b/rsocket-transport-websocket/src/client.rs @@ -2,7 +2,9 @@ use std::net::SocketAddr; use rsocket_rust::{async_trait, error::RSocketError, transport::Transport, Result}; use tokio::net::TcpStream; -use tokio_tungstenite::{accept_async, connect_async, tungstenite::handshake::client::Request, MaybeTlsStream}; +use tokio_tungstenite::{ + accept_async, connect_async, tungstenite::handshake::client::Request, MaybeTlsStream, +}; use url::Url; use super::connection::WebsocketConnection; diff --git a/rsocket-transport-websocket/src/lib.rs b/rsocket-transport-websocket/src/lib.rs index 4a34f09..8dfac3d 100644 --- a/rsocket-transport-websocket/src/lib.rs +++ b/rsocket-transport-websocket/src/lib.rs @@ -12,10 +12,11 @@ pub use server::WebsocketServerTransport; #[cfg(test)] mod test_websocket { - use super::*; use rsocket_rust::prelude::*; use tokio_tungstenite::tungstenite::client::IntoClientRequest; + use super::*; + #[ignore] #[tokio::test] async fn test_client() { diff --git a/rsocket/README.md b/rsocket/README.md index 76cda74..ae1f614 100644 --- a/rsocket/README.md +++ b/rsocket/README.md @@ -136,4 +136,3 @@ impl RSocket for RedisDao { } ``` - diff --git a/rsocket/src/transport/socket.rs b/rsocket/src/transport/socket.rs index e11c419..fdc796f 100644 --- a/rsocket/src/transport/socket.rs +++ b/rsocket/src/transport/socket.rs @@ -6,8 +6,8 @@ use async_stream::stream; use async_trait::async_trait; use bytes::{Buf, BufMut, Bytes, BytesMut}; use dashmap::{mapref::entry::Entry, DashMap}; -use futures::{Sink, SinkExt, Stream, StreamExt}; use futures::future::{AbortHandle, Abortable}; +use futures::{Sink, SinkExt, Stream, StreamExt}; use tokio::sync::{mpsc, oneshot, RwLock}; use super::fragmentation::{Joiner, Splitter}; @@ -294,7 +294,7 @@ impl DuplexSocket { #[inline] async fn on_cancel(&mut self, sid: u32, _flag: u16) { - if let Some((sid,abort_handle)) = self.abort_handles.remove(&sid) { + if let Some((sid, abort_handle)) = self.abort_handles.remove(&sid) { abort_handle.abort(); } self.joiners.remove(&sid); @@ -334,7 +334,7 @@ impl DuplexSocket { error!("response successful payload for REQUEST_RESPONSE failed: sid={}",sid); } } else if sender.send(Ok(None)).is_err() { - error!("response successful payload for REQUEST_RESPONSE failed: sid={}",sid); + error!("response successful payload for REQUEST_RESPONSE failed: sid={}",sid); } } _ => unreachable!(), @@ -476,10 +476,7 @@ impl DuplexSocket { runtime::spawn(async move { let (abort_handle, abort_registration) = AbortHandle::new_pair(); abort_handles.insert(sid, abort_handle); - let mut payloads = Abortable::new( - responder.request_stream(input), - abort_registration - ); + let mut payloads = Abortable::new(responder.request_stream(input), abort_registration); while let Some(next) = payloads.next().await { match next { Ok(it) => { @@ -518,10 +515,7 @@ impl DuplexSocket { })); let (abort_handle, abort_registration) = AbortHandle::new_pair(); abort_handles.insert(sid, abort_handle); - let mut outputs = Abortable::new( - outputs, - abort_registration - ); + let mut outputs = Abortable::new(outputs, abort_registration); // TODO: support custom RequestN. let request_n = frame::RequestN::builder(sid, 0).build(); diff --git a/rustfmt.toml b/rustfmt.toml index ba9b0e4..3a26366 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,2 +1 @@ -edition = 2021" -group_imports="StdExternalCrate" +edition = "2021" From a99150ae322800cc0aad4be83cc1989abeaf52dd Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Wed, 31 May 2023 21:24:51 +0800 Subject: [PATCH 68/70] chore(release): prepare for v0.7.4 --- README.md | 6 +++--- rsocket-messaging/Cargo.toml | 2 +- rsocket-transport-tcp/Cargo.toml | 2 +- rsocket-transport-wasm/Cargo.toml | 2 +- rsocket-transport-websocket/Cargo.toml | 2 +- rsocket/Cargo.toml | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index fa6361f..617c6cb 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,11 @@ Add dependencies in your `Cargo.toml`. ```toml [dependencies] tokio = "1.0.3" -rsocket_rust = "0.7.3" +rsocket_rust = "0.7" # add transport dependencies: -# rsocket_rust_transport_tcp = "0.7.3" -# rsocket_rust_transport_websocket = "0.7.3" +# rsocket_rust_transport_tcp = "0.7" +# rsocket_rust_transport_websocket = "0.7" ``` ### Server diff --git a/rsocket-messaging/Cargo.toml b/rsocket-messaging/Cargo.toml index 7edb572..762b19e 100644 --- a/rsocket-messaging/Cargo.toml +++ b/rsocket-messaging/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_messaging" -version = "0.7.3" +version = "0.7.4" authors = ["Jeffsky "] edition = "2021" license = "Apache-2.0" diff --git a/rsocket-transport-tcp/Cargo.toml b/rsocket-transport-tcp/Cargo.toml index d24a243..b6b54e7 100644 --- a/rsocket-transport-tcp/Cargo.toml +++ b/rsocket-transport-tcp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_tcp" -version = "0.7.3" +version = "0.7.4" authors = ["Jeffsky "] edition = "2021" license = "Apache-2.0" diff --git a/rsocket-transport-wasm/Cargo.toml b/rsocket-transport-wasm/Cargo.toml index fa51ed9..caf4a01 100644 --- a/rsocket-transport-wasm/Cargo.toml +++ b/rsocket-transport-wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_wasm" -version = "0.7.3" +version = "0.7.4" authors = ["Jeffsky "] edition = "2021" license = "Apache-2.0" diff --git a/rsocket-transport-websocket/Cargo.toml b/rsocket-transport-websocket/Cargo.toml index 43b621d..36f763c 100644 --- a/rsocket-transport-websocket/Cargo.toml +++ b/rsocket-transport-websocket/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust_transport_websocket" -version = "0.7.3" +version = "0.7.4" authors = ["Jeffsky "] edition = "2021" license = "Apache-2.0" diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index 0855e6f..5c9458e 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust" -version = "0.7.3" +version = "0.7.4" authors = ["Jeffsky "] edition = "2021" license = "Apache-2.0" From fd4300045f0c866087782b06d308a9d97a5fbf0b Mon Sep 17 00:00:00 2001 From: Jeffsky Date: Tue, 26 Dec 2023 20:19:57 +0800 Subject: [PATCH 69/70] fix: use FnOnce as client acceptor instead of Fn --- rsocket/Cargo.toml | 2 +- rsocket/src/spi.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rsocket/Cargo.toml b/rsocket/Cargo.toml index 5c9458e..ea0e09f 100644 --- a/rsocket/Cargo.toml +++ b/rsocket/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rsocket_rust" -version = "0.7.4" +version = "0.7.5" authors = ["Jeffsky "] edition = "2021" license = "Apache-2.0" diff --git a/rsocket/src/spi.rs b/rsocket/src/spi.rs index 070b873..6a2b942 100644 --- a/rsocket/src/spi.rs +++ b/rsocket/src/spi.rs @@ -7,7 +7,7 @@ use futures::Stream; use crate::payload::{Payload, SetupPayload}; use crate::Result; -pub type ClientResponder = Box Box>; +pub type ClientResponder = Box Box>; pub type ServerResponder = Box) -> Result>>; From ebbafca8b3fa7a202c517c5ee2d7b81d10f41b9a Mon Sep 17 00:00:00 2001 From: Xylaant Date: Wed, 26 Jun 2024 08:28:23 -0400 Subject: [PATCH 70/70] feat: remove cancel task, which was causing a circular reference (#65) Provide user with a weak reference to Requester, when in Server mode, to allow socket to close properly --- rsocket/src/core/client.rs | 31 +- rsocket/src/core/server.rs | 3 +- rsocket/src/transport/mod.rs | 2 +- rsocket/src/transport/socket.rs | 520 +++++++++++++++++++------------- 4 files changed, 326 insertions(+), 230 deletions(-) diff --git a/rsocket/src/core/client.rs b/rsocket/src/core/client.rs index f846bb9..c014ca3 100644 --- a/rsocket/src/core/client.rs +++ b/rsocket/src/core/client.rs @@ -14,14 +14,14 @@ use crate::payload::{Payload, SetupPayload, SetupPayloadBuilder}; use crate::runtime; use crate::spi::{ClientResponder, Flux, RSocket}; use crate::transport::{ - self, Connection, DuplexSocket, FrameSink, FrameStream, Splitter, Transport, + self, Connection, DuplexSocket, FrameSink, FrameStream, ClientRequester, Splitter, Transport, }; use crate::Result; #[derive(Clone)] pub struct Client { closed: Arc, - socket: DuplexSocket, + requester: ClientRequester, closing: mpsc::Sender<()>, } @@ -130,9 +130,9 @@ where let (snd_tx, mut snd_rx) = mpsc::unbounded_channel::(); let cloned_snd_tx = snd_tx.clone(); - let mut socket = DuplexSocket::new(1, snd_tx, splitter).await; + let mut socket = DuplexSocket::new(1, snd_tx, splitter); - let mut cloned_socket = socket.clone(); + let requester = socket.client_requester(); if let Some(f) = self.responder { let responder = f(); @@ -211,10 +211,13 @@ where } }); + + socket.setup(setup).await?; + // process frames runtime::spawn(async move { while let Some(next) = read_rx.recv().await { - if let Err(e) = cloned_socket.dispatch(next, None).await { + if let Err(e) = socket.dispatch(next, None).await { error!("dispatch frame failed: {}", e); break; } @@ -237,16 +240,14 @@ where } }); - socket.setup(setup).await?; - - Ok(Client::new(socket, close_notify, closing)) + Ok(Client::new(requester, close_notify, closing)) } } impl Client { - fn new(socket: DuplexSocket, closed: Arc, closing: mpsc::Sender<()>) -> Client { + fn new(requester: ClientRequester, closed: Arc, closing: mpsc::Sender<()>) -> Client { Client { - socket, + requester, closed, closing, } @@ -260,22 +261,22 @@ impl Client { #[async_trait] impl RSocket for Client { async fn metadata_push(&self, req: Payload) -> Result<()> { - self.socket.metadata_push(req).await + self.requester.metadata_push(req).await } async fn fire_and_forget(&self, req: Payload) -> Result<()> { - self.socket.fire_and_forget(req).await + self.requester.fire_and_forget(req).await } async fn request_response(&self, req: Payload) -> Result> { - self.socket.request_response(req).await + self.requester.request_response(req).await } fn request_stream(&self, req: Payload) -> Flux> { - self.socket.request_stream(req) + self.requester.request_stream(req) } fn request_channel(&self, reqs: Flux>) -> Flux> { - self.socket.request_channel(reqs) + self.requester.request_channel(reqs) } } diff --git a/rsocket/src/core/server.rs b/rsocket/src/core/server.rs index 3b39fb5..5e79f1d 100644 --- a/rsocket/src/core/server.rs +++ b/rsocket/src/core/server.rs @@ -114,7 +114,7 @@ where // Init duplex socket. let (snd_tx, mut snd_rx) = mpsc::unbounded_channel::(); - let mut socket = DuplexSocket::new(0, snd_tx, splitter).await; + let mut socket = DuplexSocket::new(0, snd_tx, splitter); // Begin loop for writing frames. runtime::spawn(async move { @@ -154,7 +154,6 @@ where break; } } - Ok(()) } } diff --git a/rsocket/src/transport/mod.rs b/rsocket/src/transport/mod.rs index 9adddcb..d040d86 100644 --- a/rsocket/src/transport/mod.rs +++ b/rsocket/src/transport/mod.rs @@ -4,5 +4,5 @@ mod socket; mod spi; pub(crate) use fragmentation::{Joiner, Splitter, MIN_MTU}; -pub(crate) use socket::DuplexSocket; +pub(crate) use socket::{ClientRequester,DuplexSocket}; pub use spi::*; diff --git a/rsocket/src/transport/socket.rs b/rsocket/src/transport/socket.rs index fdc796f..de0ec93 100644 --- a/rsocket/src/transport/socket.rs +++ b/rsocket/src/transport/socket.rs @@ -1,6 +1,6 @@ use std::future::Future; use std::pin::Pin; -use std::sync::Arc; +use std::sync::{Arc, Weak}; use async_stream::stream; use async_trait::async_trait; @@ -20,19 +20,31 @@ use crate::spi::{Flux, RSocket, ServerResponder}; use crate::utils::EmptyRSocket; use crate::{runtime, Result}; -#[derive(Clone)] -pub(crate) struct DuplexSocket { +struct DuplexSocketInner { seq: StreamID, responder: Responder, tx: mpsc::UnboundedSender, - handlers: Arc>, - canceller: mpsc::Sender, + handlers: DashMap, splitter: Option, - joiners: Arc>, - /// AbortHandles for streams and channels associated by sid + joiners: DashMap, + /// AbortHandles for Response futures/streams abort_handles: Arc>, } +#[derive(Clone)] +pub(crate) struct ClientRequester { + inner: Arc, +} + +#[derive(Clone)] +pub(crate) struct ServerRequester { + inner: Weak, +} + +pub(crate) struct DuplexSocket { + inner: Arc, +} + #[derive(Clone)] struct Responder { inner: Arc>>, @@ -41,36 +53,41 @@ struct Responder { #[derive(Debug)] enum Handler { ReqRR(oneshot::Sender>>), - ResRR(Counter), ReqRS(mpsc::Sender>), ReqRC(mpsc::Sender>), } -impl DuplexSocket { - pub(crate) async fn new( +struct Cancel {} + +impl DuplexSocketInner { + fn new( first_stream_id: u32, tx: mpsc::UnboundedSender, splitter: Option, - ) -> DuplexSocket { + ) -> Self { let (canceller_tx, canceller_rx) = mpsc::channel::(32); - let socket = DuplexSocket { + let this = Self { seq: StreamID::from(first_stream_id), tx, - canceller: canceller_tx, responder: Responder::new(), - handlers: Arc::new(DashMap::new()), - joiners: Arc::new(DashMap::new()), + handlers: DashMap::new(), + joiners: DashMap::new(), splitter, abort_handles: Arc::new(DashMap::new()), }; + this + } +} - let cloned_socket = socket.clone(); - - runtime::spawn(async move { - cloned_socket.loop_canceller(canceller_rx).await; - }); - - socket +impl DuplexSocket { + pub(crate) fn new( + first_stream_id: u32, + tx: mpsc::UnboundedSender, + splitter: Option, + ) -> DuplexSocket { + DuplexSocket { + inner: Arc::new(DuplexSocketInner::new(first_stream_id, tx, splitter)), + } } pub(crate) async fn setup(&mut self, setup: SetupPayload) -> Result<()> { @@ -90,19 +107,12 @@ impl DuplexSocket { if let Some(b) = m { bu = bu.set_metadata(b); } - self.tx.send(bu.build()).map_err(|e| e.into()) + self.inner.tx.send(bu.build()).map_err(|e| e.into()) } #[inline] - async fn register_handler(&self, sid: u32, handler: Handler) { - self.handlers.insert(sid, handler); - } - - #[inline] - async fn loop_canceller(&self, mut rx: mpsc::Receiver) { - while let Some(sid) = rx.recv().await { - self.handlers.remove(&sid); - } + fn register_handler(&self, sid: u32, handler: Handler) { + self.inner.handlers.insert(sid, handler); } pub(crate) async fn dispatch( @@ -132,7 +142,7 @@ impl DuplexSocket { .set_code(error::ERR_REJECT_SETUP) .set_data(Bytes::from(errmsg)) .build(); - if self.tx.send(sending).is_err() { + if self.inner.tx.send(sending).is_err() { error!("Reject setup failed"); } } @@ -198,7 +208,8 @@ impl DuplexSocket { let sid = input.get_stream_id(); if input.get_flag() & Frame::FLAG_FOLLOW != 0 { // TODO: check conflict - self.joiners + self.inner + .joiners .entry(sid) .or_insert_with(Joiner::new) .push(input); @@ -209,7 +220,7 @@ impl DuplexSocket { return Some(input); } - match self.joiners.remove(&sid) { + match self.inner.joiners.remove(&sid) { None => Some(input), Some((_, mut joiner)) => { joiner.push(input); @@ -263,9 +274,9 @@ impl DuplexSocket { #[inline] async fn on_error(&mut self, sid: u32, flag: u16, input: frame::Error) { - self.joiners.remove(&sid); + self.inner.joiners.remove(&sid); // pick handler - if let Some((_, handler)) = self.handlers.remove(&sid) { + if let Some((_, handler)) = self.inner.handlers.remove(&sid) { let desc = input .get_data_utf8() .map(|it| it.to_string()) @@ -277,7 +288,6 @@ impl DuplexSocket { error!("respond with error for REQUEST_RESPONSE failed!"); } } - Handler::ResRR(_) => unreachable!(), Handler::ReqRS(tx) => { if (tx.send(Err(e.into())).await).is_err() { error!("respond with error for REQUEST_STREAM failed!"); @@ -294,11 +304,11 @@ impl DuplexSocket { #[inline] async fn on_cancel(&mut self, sid: u32, _flag: u16) { - if let Some((sid, abort_handle)) = self.abort_handles.remove(&sid) { + if let Some((sid, abort_handle)) = self.inner.abort_handles.remove(&sid) { abort_handle.abort(); } - self.joiners.remove(&sid); - if let Some((_, handler)) = self.handlers.remove(&sid) { + self.inner.joiners.remove(&sid); + if let Some((_, handler)) = self.inner.handlers.remove(&sid) { let e: Result<_> = Err(RSocketError::RequestCancelled("request has been cancelled".into()).into()); match handler { @@ -308,10 +318,6 @@ impl DuplexSocket { error!("notify cancel for REQUEST_RESPONSE failed: sid={}", sid); } } - Handler::ResRR(c) => { - let lefts = c.count_down(); - info!("REQUEST_RESPONSE {} cancelled: lefts={}", sid, lefts); - } Handler::ReqRS(sender) => { info!("REQUEST_STREAM {} cancelled!", sid); } @@ -324,7 +330,7 @@ impl DuplexSocket { #[inline] async fn on_payload(&mut self, sid: u32, flag: u16, input: Payload) { - match self.handlers.entry(sid) { + match self.inner.handlers.entry(sid) { Entry::Occupied(o) => { match o.get() { Handler::ReqRR(_) => match o.remove() { @@ -339,7 +345,6 @@ impl DuplexSocket { } _ => unreachable!(), }, - Handler::ResRR(c) => unreachable!(), Handler::ReqRS(sender) => { if flag & Frame::FLAG_NEXT != 0 { if sender.is_closed() { @@ -379,13 +384,13 @@ impl DuplexSocket { #[inline] fn send_cancel_frame(&self, sid: u32) { let cancel_frame = frame::Cancel::builder(sid, Frame::FLAG_COMPLETE).build(); - if let Err(e) = self.tx.send(cancel_frame) { + if let Err(e) = self.inner.tx.send(cancel_frame) { error!("Sending CANCEL frame failed: sid={}, reason: {}", sid, e); } } pub(crate) async fn bind_responder(&self, responder: Box) { - self.responder.set(responder).await; + self.inner.responder.set(responder).await; } #[inline] @@ -398,12 +403,12 @@ impl DuplexSocket { ) -> Result<()> { match acceptor { None => { - self.responder.set(Box::new(EmptyRSocket)).await; + self.inner.responder.set(Box::new(EmptyRSocket)).await; Ok(()) } - Some(gen) => match gen(setup, Box::new(self.clone())) { + Some(gen) => match gen(setup, Box::new(self.server_requester())) { Ok(it) => { - self.responder.set(it).await; + self.inner.responder.set(it).await; Ok(()) } Err(e) => Err(e), @@ -413,36 +418,36 @@ impl DuplexSocket { #[inline] async fn on_fire_and_forget(&mut self, sid: u32, input: Payload) { - if let Err(e) = self.responder.fire_and_forget(input).await { + // TODO: Spawning a task here in case responer call goes pending, which would hold + // up the entire dispatch loop + if let Err(e) = self.inner.responder.fire_and_forget(input).await { error!("respond fire_and_forget failed: {:?}", e); } } #[inline] async fn on_request_response(&mut self, sid: u32, _flag: u16, input: Payload) { - let responder = self.responder.clone(); - let canceller = self.canceller.clone(); - let mut tx = self.tx.clone(); - let splitter = self.splitter.clone(); - let counter = Counter::new(2); - self.register_handler(sid, Handler::ResRR(counter.clone())) - .await; + let responder = self.inner.responder.clone(); + + let mut tx = self.inner.tx.clone(); + let splitter = self.inner.splitter.clone(); + let (abort_handle, abort_registration) = AbortHandle::new_pair(); + let abort_handles = self.inner.abort_handles.clone(); runtime::spawn(async move { - // TODO: use future select - let result = responder.request_response(input).await; - if counter.count_down() == 0 { + + abort_handles.insert(sid, abort_handle); + let result= Abortable::new(responder.request_response(input), abort_registration).await; + abort_handles.remove(&sid); + + // Abort for futures adds an extra result wrapper, so unwrap that and continue + let Ok(result) = result else { // cancelled return; - } - - // async remove canceller - if (canceller.send(sid).await).is_err() { - error!("Send canceller failed: sid={}", sid); - } + }; match result { Ok(Some(res)) => { - Self::try_send_payload( + DuplexSocketInner::try_send_payload( &splitter, &mut tx, sid, @@ -452,7 +457,7 @@ impl DuplexSocket { .await; } Ok(None) => { - Self::try_send_complete(&mut tx, sid, Frame::FLAG_COMPLETE).await; + DuplexSocketInner::try_send_complete(&mut tx, sid, Frame::FLAG_COMPLETE).await; } Err(e) => { let sending = frame::Error::builder(sid, 0) @@ -469,10 +474,10 @@ impl DuplexSocket { #[inline] async fn on_request_stream(&self, sid: u32, flag: u16, input: Payload) { - let responder = self.responder.clone(); - let mut tx = self.tx.clone(); - let splitter = self.splitter.clone(); - let abort_handles = self.abort_handles.clone(); + let responder = self.inner.responder.clone(); + let mut tx = self.inner.tx.clone(); + let splitter = self.inner.splitter.clone(); + let abort_handles = self.inner.abort_handles.clone(); runtime::spawn(async move { let (abort_handle, abort_registration) = AbortHandle::new_pair(); abort_handles.insert(sid, abort_handle); @@ -480,7 +485,14 @@ impl DuplexSocket { while let Some(next) = payloads.next().await { match next { Ok(it) => { - Self::try_send_payload(&splitter, &mut tx, sid, it, Frame::FLAG_NEXT).await; + DuplexSocketInner::try_send_payload( + &splitter, + &mut tx, + sid, + it, + Frame::FLAG_NEXT, + ) + .await; } Err(e) => { let sending = frame::Error::builder(sid, 0) @@ -500,12 +512,12 @@ impl DuplexSocket { #[inline] async fn on_request_channel(&self, sid: u32, flag: u16, first: Payload) { - let responder = self.responder.clone(); - let tx = self.tx.clone(); + let responder = self.inner.responder.clone(); + let tx = self.inner.tx.clone(); let (sender, mut receiver) = mpsc::channel::>(32); sender.send(Ok(first)).await.expect("Send failed!"); - self.register_handler(sid, Handler::ReqRC(sender)).await; - let abort_handles = self.abort_handles.clone(); + self.register_handler(sid, Handler::ReqRC(sender)); + let abort_handles = self.inner.abort_handles.clone(); runtime::spawn(async move { // respond client channel let outputs = responder.request_channel(Box::pin(stream! { @@ -554,7 +566,9 @@ impl DuplexSocket { #[inline] async fn on_metadata_push(&mut self, input: Payload) { - if let Err(e) = self.responder.metadata_push(input).await { + // TODO: Spawning a task here in case responer call goes pending, which would hold + // up the entire dispatch loop + if let Err(e) = self.inner.responder.metadata_push(input).await { error!("response metadata_push failed: {:?}", e); } } @@ -566,139 +580,26 @@ impl DuplexSocket { if let Some(b) = data { sending = sending.set_data(b); } - if let Err(e) = self.tx.send(sending.build()) { + if let Err(e) = self.inner.tx.send(sending.build()) { error!("respond KEEPALIVE failed: {}", e); } } - #[inline] - async fn try_send_channel( - splitter: &Option, - tx: &mut mpsc::UnboundedSender, - sid: u32, - res: Payload, - flag: u16, - ) { - // TODO - match splitter { - Some(sp) => { - let mut cuts: usize = 0; - let mut prev: Option = None; - for next in sp.cut(res, 4) { - if let Some(cur) = prev.take() { - let sending = if cuts == 1 { - frame::RequestChannel::builder(sid, flag | Frame::FLAG_FOLLOW) - .set_all(cur.split()) - .build() - } else { - frame::Payload::builder(sid, Frame::FLAG_FOLLOW) - .set_all(cur.split()) - .build() - }; - // send frame - if let Err(e) = tx.send(sending) { - error!("send request_channel failed: {}", e); - return; - } - } - prev = Some(next); - cuts += 1; - } - - let sending = if cuts == 0 { - frame::RequestChannel::builder(sid, flag).build() - } else if cuts == 1 { - frame::RequestChannel::builder(sid, flag) - .set_all(prev.unwrap().split()) - .build() - } else { - frame::Payload::builder(sid, 0) - .set_all(prev.unwrap().split()) - .build() - }; - // send frame - if let Err(e) = tx.send(sending) { - error!("send request_channel failed: {}", e); - } - } - None => { - let sending = frame::RequestChannel::builder(sid, flag) - .set_all(res.split()) - .build(); - if let Err(e) = tx.send(sending) { - error!("send request_channel failed: {}", e); - } - } + pub(crate) fn client_requester(&self) -> ClientRequester { + ClientRequester { + inner: self.inner.clone(), } } - #[inline] - async fn try_send_complete(tx: &mut mpsc::UnboundedSender, sid: u32, flag: u16) { - let sending = frame::Payload::builder(sid, flag).build(); - if let Err(e) = tx.send(sending) { - error!("respond failed: {}", e); - } - } - - #[inline] - async fn try_send_payload( - splitter: &Option, - tx: &mut mpsc::UnboundedSender, - sid: u32, - res: Payload, - flag: u16, - ) { - match splitter { - Some(sp) => { - let mut cuts: usize = 0; - let mut prev: Option = None; - for next in sp.cut(res, 0) { - if let Some(cur) = prev.take() { - let sending = if cuts == 1 { - frame::Payload::builder(sid, flag | Frame::FLAG_FOLLOW) - .set_all(cur.split()) - .build() - } else { - frame::Payload::builder(sid, Frame::FLAG_FOLLOW) - .set_all(cur.split()) - .build() - }; - // send frame - if let Err(e) = tx.send(sending) { - error!("send payload failed: {}", e); - return; - } - } - prev = Some(next); - cuts += 1; - } - - let sending = if cuts == 0 { - frame::Payload::builder(sid, flag).build() - } else { - frame::Payload::builder(sid, flag) - .set_all(prev.unwrap().split()) - .build() - }; - // send frame - if let Err(e) = tx.send(sending) { - error!("send payload failed: {}", e); - } - } - None => { - let sending = frame::Payload::builder(sid, flag) - .set_all(res.split()) - .build(); - if let Err(e) = tx.send(sending) { - error!("respond failed: {}", e); - } - } + pub(crate) fn server_requester(&self) -> ServerRequester { + ServerRequester { + inner: Arc::downgrade(&self.inner), } } } -#[async_trait] -impl RSocket for DuplexSocket { +// These are the immplementation functions for the requesters below +impl DuplexSocketInner { async fn metadata_push(&self, req: Payload) -> Result<()> { let sid = self.seq.next(); let tx = self.tx.clone(); @@ -767,14 +668,13 @@ impl RSocket for DuplexSocket { async fn request_response(&self, req: Payload) -> Result> { let (tx, rx) = oneshot::channel::>>(); let sid = self.seq.next(); - let handlers = self.handlers.clone(); let sender = self.tx.clone(); - let splitter = self.splitter.clone(); + // Register handler + self.handlers.insert(sid, Handler::ReqRR(tx)); + runtime::spawn(async move { - // register handler - handlers.insert(sid, Handler::ReqRR(tx)); match splitter { Some(sp) => { let mut cuts: usize = 0; @@ -841,10 +741,9 @@ impl RSocket for DuplexSocket { let tx = self.tx.clone(); // register handler let (sender, mut receiver) = mpsc::channel::>(32); - let handlers = self.handlers.clone(); + self.handlers.insert(sid, Handler::ReqRS(sender)); let splitter = self.splitter.clone(); runtime::spawn(async move { - handlers.insert(sid, Handler::ReqRS(sender)); match splitter { Some(sp) => { let mut cuts: usize = 0; @@ -909,12 +808,12 @@ impl RSocket for DuplexSocket { fn request_channel(&self, mut reqs: Flux>) -> Flux> { let sid = self.seq.next(); let mut tx = self.tx.clone(); - // register handler + let (sender, mut receiver) = mpsc::channel::>(32); - let handlers = self.handlers.clone(); + // register handler + self.handlers.insert(sid, Handler::ReqRC(sender)); let splitter = self.splitter.clone(); runtime::spawn(async move { - handlers.insert(sid, Handler::ReqRC(sender)); let mut first = true; while let Some(next) = reqs.next().await { match next { @@ -950,6 +849,131 @@ impl RSocket for DuplexSocket { } }) } + + #[inline] + async fn try_send_channel( + splitter: &Option, + tx: &mut mpsc::UnboundedSender, + sid: u32, + res: Payload, + flag: u16, + ) { + // TODO + match splitter { + Some(sp) => { + let mut cuts: usize = 0; + let mut prev: Option = None; + for next in sp.cut(res, 4) { + if let Some(cur) = prev.take() { + let sending = if cuts == 1 { + frame::RequestChannel::builder(sid, flag | Frame::FLAG_FOLLOW) + .set_all(cur.split()) + .build() + } else { + frame::Payload::builder(sid, Frame::FLAG_FOLLOW) + .set_all(cur.split()) + .build() + }; + // send frame + if let Err(e) = tx.send(sending) { + error!("send request_channel failed: {}", e); + return; + } + } + prev = Some(next); + cuts += 1; + } + + let sending = if cuts == 0 { + frame::RequestChannel::builder(sid, flag).build() + } else if cuts == 1 { + frame::RequestChannel::builder(sid, flag) + .set_all(prev.unwrap().split()) + .build() + } else { + frame::Payload::builder(sid, 0) + .set_all(prev.unwrap().split()) + .build() + }; + // send frame + if let Err(e) = tx.send(sending) { + error!("send request_channel failed: {}", e); + } + } + None => { + let sending = frame::RequestChannel::builder(sid, flag) + .set_all(res.split()) + .build(); + if let Err(e) = tx.send(sending) { + error!("send request_channel failed: {}", e); + } + } + } + } + + #[inline] + async fn try_send_complete(tx: &mut mpsc::UnboundedSender, sid: u32, flag: u16) { + let sending = frame::Payload::builder(sid, flag).build(); + if let Err(e) = tx.send(sending) { + error!("respond failed: {}", e); + } + } + + #[inline] + async fn try_send_payload( + splitter: &Option, + tx: &mut mpsc::UnboundedSender, + sid: u32, + res: Payload, + flag: u16, + ) { + match splitter { + Some(sp) => { + let mut cuts: usize = 0; + let mut prev: Option = None; + for next in sp.cut(res, 0) { + if let Some(cur) = prev.take() { + let sending = if cuts == 1 { + frame::Payload::builder(sid, flag | Frame::FLAG_FOLLOW) + .set_all(cur.split()) + .build() + } else { + frame::Payload::builder(sid, Frame::FLAG_FOLLOW) + .set_all(cur.split()) + .build() + }; + // send frame + if let Err(e) = tx.send(sending) { + error!("send payload failed: {}", e); + return; + } + } + prev = Some(next); + cuts += 1; + } + + let sending = if cuts == 0 { + frame::Payload::builder(sid, flag).build() + } else { + frame::Payload::builder(sid, flag) + .set_all(prev.unwrap().split()) + .build() + }; + // send frame + if let Err(e) = tx.send(sending) { + error!("send payload failed: {}", e); + } + } + None => { + let sending = frame::Payload::builder(sid, flag) + .set_all(res.split()) + .build(); + if let Err(e) = tx.send(sending) { + error!("respond failed: {}", e); + } + } + } + } } impl From> for Responder { @@ -1013,3 +1037,75 @@ impl RSocket for Responder { }) } } + +#[async_trait] +impl RSocket for ClientRequester { + /// Metadata-Push interaction model of RSocket. + async fn metadata_push(&self, req: Payload) -> Result<()> { + self.inner.metadata_push(req).await + } + /// Fire and Forget interaction model of RSocket. + async fn fire_and_forget(&self, req: Payload) -> Result<()> { + self.inner.fire_and_forget(req).await + } + /// Request-Response interaction model of RSocket. + async fn request_response(&self, req: Payload) -> Result> { + self.inner.request_response(req).await + } + /// Request-Stream interaction model of RSocket. + fn request_stream(&self, req: Payload) -> Flux> { + self.inner.request_stream(req) + } + /// Request-Channel interaction model of RSocket. + fn request_channel(&self, reqs: Flux>) -> Flux> { + self.inner.request_channel(reqs) + } +} + +// This implementation, uses the async function trait, as it needs to capture the ugpraded +// Arc, at least until it returns +#[async_trait] +impl RSocket for ServerRequester { + /// Metadata-Push interaction model of RSocket. + async fn metadata_push(&self, req: Payload) -> Result<()> { + match self.inner.upgrade() { + Some(inner) => inner.metadata_push(req).await, + None => Err(RSocketError::ConnectionClosed("close".into()).into()), + } + } + /// Fire and Forget interaction model of RSocket. + async fn fire_and_forget(&self, req: Payload) -> Result<()> { + match self.inner.upgrade() { + Some(inner) => inner.fire_and_forget(req).await, + None => Err(RSocketError::ConnectionClosed("closed".into()).into()), + } + } + /// Request-Response interaction model of RSocket. + async fn request_response(&self, req: Payload) -> Result> { + match self.inner.upgrade() { + Some(inner) => inner.request_response(req).await, + None => Err(RSocketError::ConnectionClosed("closed".into()).into()), + } + } + /// Request-Stream interaction model of RSocket. + fn request_stream(&self, req: Payload) -> Flux> { + use futures::{future, stream}; + + match self.inner.upgrade() { + Some(inner) => inner.request_stream(req), + None => Box::pin(stream::once(future::ready(Err( + RSocketError::ConnectionClosed("closed".into()).into(), + )))), + } + } + /// Request-Channel interaction model of RSocket. + fn request_channel(&self, reqs: Flux>) -> Flux> { + use futures::{future, stream}; + match self.inner.upgrade() { + Some(inner) => inner.request_channel(reqs), + None => Box::pin(stream::once(future::ready(Err( + RSocketError::ConnectionClosed("closed".into()).into(), + )))), + } + } +}