diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index eef0e83ac..6db651b08 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -56,13 +56,6 @@ test-linux-stable: <<: *only <<: *test_and_build -test-windows-stable: - stage: test - <<: *test_and_build - <<: *only - tags: - - rust-windows - test-mac-stable: stage: test <<: *test_and_build diff --git a/core-client/Cargo.toml b/core-client/Cargo.toml index ac64b4094..d8414b041 100644 --- a/core-client/Cargo.toml +++ b/core-client/Cargo.toml @@ -8,7 +8,7 @@ keywords = ["jsonrpc", "json-rpc", "json", "rpc", "serde"] license = "MIT" name = "jsonrpc-core-client" repository = "https://github.com/paritytech/jsonrpc" -version = "17.0.0" +version = "17.1.0" categories = [ "asynchronous", @@ -26,7 +26,7 @@ ipc = ["jsonrpc-client-transports/ipc"] arbitrary_precision = ["jsonrpc-client-transports/arbitrary_precision"] [dependencies] -jsonrpc-client-transports = { version = "17.0", path = "./transports", default-features = false } +jsonrpc-client-transports = { version = "17.1", path = "./transports", default-features = false } futures = { version = "0.3", features = [ "compat" ] } [badges] diff --git a/core-client/transports/Cargo.toml b/core-client/transports/Cargo.toml index f92978f51..af4b3a62a 100644 --- a/core-client/transports/Cargo.toml +++ b/core-client/transports/Cargo.toml @@ -8,7 +8,7 @@ keywords = ["jsonrpc", "json-rpc", "json", "rpc", "serde"] license = "MIT" name = "jsonrpc-client-transports" repository = "https://github.com/paritytech/jsonrpc" -version = "17.0.0" +version = "17.1.0" categories = [ "asynchronous", @@ -37,8 +37,8 @@ arbitrary_precision = ["serde_json/arbitrary_precision", "jsonrpc-core/arbitrary [dependencies] derive_more = "0.99" futures = "0.3" -jsonrpc-core = { version = "17.0", path = "../../core" } -jsonrpc-pubsub = { version = "17.0", path = "../../pubsub" } +jsonrpc-core = { version = "17.1", path = "../../core" } +jsonrpc-pubsub = { version = "17.1", path = "../../pubsub" } log = "0.4" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" @@ -46,15 +46,15 @@ url = "1.7" hyper = { version = "0.13", optional = true } hyper-tls = { version = "0.4", optional = true } -jsonrpc-server-utils = { version = "17.0", path = "../../server-utils", optional = true } +jsonrpc-server-utils = { version = "17.1", path = "../../server-utils", optional = true } parity-tokio-ipc = { version = "0.8", optional = true } tokio = { version = "0.2", optional = true } websocket = { version = "0.24", optional = true } [dev-dependencies] assert_matches = "1.1" -jsonrpc-http-server = { version = "17.0", path = "../../http" } -jsonrpc-ipc-server = { version = "17.0", path = "../../ipc" } +jsonrpc-http-server = { version = "17.1", path = "../../http" } +jsonrpc-ipc-server = { version = "17.1", path = "../../ipc" } lazy_static = "1.0" env_logger = "0.7" diff --git a/core-client/transports/src/lib.rs b/core-client/transports/src/lib.rs index 001177a33..efa360689 100644 --- a/core-client/transports/src/lib.rs +++ b/core-client/transports/src/lib.rs @@ -301,9 +301,10 @@ impl TypedClient { let params = match args { Value::Array(vec) => Params::Array(vec), Value::Null => Params::None, + Value::Object(map) => Params::Map(map), _ => { return Err(RpcError::Client( - "RPC params should serialize to a JSON array, or null".into(), + "RPC params should serialize to a JSON array, object or null".into(), )) } }; @@ -326,9 +327,10 @@ impl TypedClient { let params = match args { Value::Array(vec) => Params::Array(vec), Value::Null => Params::None, + Value::Object(map) => Params::Map(map), _ => { return Err(RpcError::Client( - "RPC params should serialize to a JSON array, or null".into(), + "RPC params should serialize to a JSON array, object or null".into(), )) } }; diff --git a/core-client/transports/src/transports/http.rs b/core-client/transports/src/transports/http.rs index df518340a..248b41890 100644 --- a/core-client/transports/src/transports/http.rs +++ b/core-client/transports/src/transports/http.rs @@ -273,7 +273,7 @@ mod tests { if let Err(RpcError::Other(err)) = res { if let Some(err) = err.downcast_ref::() { - assert!(err.is_connect(), format!("Expected Connection Error, got {:?}", err)) + assert!(err.is_connect(), "Expected Connection Error, got {:?}", err) } else { panic!("Expected a hyper::Error") } diff --git a/core/Cargo.toml b/core/Cargo.toml index 08536ae8c..39e2de93d 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -8,7 +8,7 @@ keywords = ["jsonrpc", "json-rpc", "json", "rpc", "serde"] license = "MIT" name = "jsonrpc-core" repository = "https://github.com/paritytech/jsonrpc" -version = "17.0.0" +version = "17.1.0" categories = [ "asynchronous", diff --git a/derive/Cargo.toml b/derive/Cargo.toml index c07ee212c..9fd65141e 100644 --- a/derive/Cargo.toml +++ b/derive/Cargo.toml @@ -7,7 +7,7 @@ homepage = "https://github.com/paritytech/jsonrpc" license = "MIT" name = "jsonrpc-derive" repository = "https://github.com/paritytech/jsonrpc" -version = "17.0.0" +version = "17.1.0" [lib] proc-macro = true @@ -20,10 +20,10 @@ proc-macro-crate = "0.1.4" [dev-dependencies] assert_matches = "1.3" -jsonrpc-core = { version = "17.0", path = "../core" } -jsonrpc-core-client = { version = "17.0", path = "../core-client" } -jsonrpc-pubsub = { version = "17.0", path = "../pubsub" } -jsonrpc-tcp-server = { version = "17.0", path = "../tcp" } +jsonrpc-core = { version = "17.1", path = "../core" } +jsonrpc-core-client = { version = "17.1", path = "../core-client" } +jsonrpc-pubsub = { version = "17.1", path = "../pubsub" } +jsonrpc-tcp-server = { version = "17.1", path = "../tcp" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" trybuild = "1.0" diff --git a/derive/tests/ui/attr-invalid-meta-list-names.stderr b/derive/tests/ui/attr-invalid-meta-list-names.stderr index 443966e27..b1beb38c4 100644 --- a/derive/tests/ui/attr-invalid-meta-list-names.stderr +++ b/derive/tests/ui/attr-invalid-meta-list-names.stderr @@ -1,8 +1,7 @@ error: Invalid attribute parameter(s): 'Xalias'. Expected 'alias' --> $DIR/attr-invalid-meta-list-names.rs:5:2 | -5 | /// Returns a protocol version - | _____^ +5 | / /// Returns a protocol version 6 | | #[rpc(name = "protocolVersion", Xalias("alias"))] 7 | | fn protocol_version(&self) -> Result; | |_________________________________________________^ diff --git a/derive/tests/ui/attr-invalid-meta-words.stderr b/derive/tests/ui/attr-invalid-meta-words.stderr index 7b5d63d17..b76def12b 100644 --- a/derive/tests/ui/attr-invalid-meta-words.stderr +++ b/derive/tests/ui/attr-invalid-meta-words.stderr @@ -1,8 +1,7 @@ error: Invalid attribute parameter(s): 'Xmeta'. Expected 'meta, raw_params' --> $DIR/attr-invalid-meta-words.rs:5:2 | -5 | /// Returns a protocol version - | _____^ +5 | / /// Returns a protocol version 6 | | #[rpc(name = "protocolVersion", Xmeta)] 7 | | fn protocol_version(&self) -> Result; | |_________________________________________________^ diff --git a/derive/tests/ui/attr-invalid-name-values.stderr b/derive/tests/ui/attr-invalid-name-values.stderr index 6811f0c3e..f308254c1 100644 --- a/derive/tests/ui/attr-invalid-name-values.stderr +++ b/derive/tests/ui/attr-invalid-name-values.stderr @@ -1,8 +1,7 @@ error: Invalid attribute parameter(s): 'Xname'. Expected 'name, returns, params' --> $DIR/attr-invalid-name-values.rs:5:2 | -5 | /// Returns a protocol version - | _____^ +5 | / /// Returns a protocol version 6 | | #[rpc(Xname = "protocolVersion")] 7 | | fn protocol_version(&self) -> Result; | |_________________________________________________^ diff --git a/derive/tests/ui/attr-missing-rpc-name.stderr b/derive/tests/ui/attr-missing-rpc-name.stderr index fca07fc75..d919e31de 100644 --- a/derive/tests/ui/attr-missing-rpc-name.stderr +++ b/derive/tests/ui/attr-missing-rpc-name.stderr @@ -1,8 +1,7 @@ error: rpc attribute should have a name e.g. `name = "method_name"` --> $DIR/attr-missing-rpc-name.rs:5:2 | -5 | /// Returns a protocol version - | _____^ +5 | / /// Returns a protocol version 6 | | #[rpc] 7 | | fn protocol_version(&self) -> Result; | |_________________________________________________^ diff --git a/derive/tests/ui/multiple-rpc-attributes.stderr b/derive/tests/ui/multiple-rpc-attributes.stderr index 05099f7e3..dddb37788 100644 --- a/derive/tests/ui/multiple-rpc-attributes.stderr +++ b/derive/tests/ui/multiple-rpc-attributes.stderr @@ -1,8 +1,7 @@ error: Expected only a single rpc attribute per method --> $DIR/multiple-rpc-attributes.rs:5:2 | -5 | /// Returns a protocol version - | _____^ +5 | / /// Returns a protocol version 6 | | #[rpc(name = "protocolVersion")] 7 | | #[rpc(name = "protocolVersionAgain")] 8 | | fn protocol_version(&self) -> Result; diff --git a/derive/tests/ui/too-many-params.stderr b/derive/tests/ui/too-many-params.stderr index b83347661..3c23fdf72 100644 --- a/derive/tests/ui/too-many-params.stderr +++ b/derive/tests/ui/too-many-params.stderr @@ -1,8 +1,7 @@ error: Maximum supported number of params is 16 --> $DIR/too-many-params.rs:5:2 | -5 | /// Has too many params - | _____^ +5 | / /// Has too many params 6 | | #[rpc(name = "tooManyParams")] 7 | | fn to_many_params( 8 | | &self, diff --git a/http/Cargo.toml b/http/Cargo.toml index b837fc444..1e6172abc 100644 --- a/http/Cargo.toml +++ b/http/Cargo.toml @@ -8,13 +8,13 @@ keywords = ["jsonrpc", "json-rpc", "json", "rpc", "server"] license = "MIT" name = "jsonrpc-http-server" repository = "https://github.com/paritytech/jsonrpc" -version = "17.0.0" +version = "17.1.0" [dependencies] futures = "0.3" hyper = "0.13" -jsonrpc-core = { version = "17.0", path = "../core" } -jsonrpc-server-utils = { version = "17.0", path = "../server-utils" } +jsonrpc-core = { version = "17.1", path = "../core" } +jsonrpc-server-utils = { version = "17.1", path = "../server-utils" } log = "0.4" net2 = "0.2" parking_lot = "0.11.0" diff --git a/ipc/Cargo.toml b/ipc/Cargo.toml index cf2b9bad4..0eef09da3 100644 --- a/ipc/Cargo.toml +++ b/ipc/Cargo.toml @@ -7,14 +7,14 @@ homepage = "https://github.com/paritytech/jsonrpc" license = "MIT" name = "jsonrpc-ipc-server" repository = "https://github.com/paritytech/jsonrpc" -version = "17.0.1" +version = "17.1.0" [dependencies] futures = "0.3" log = "0.4" tower-service = "0.3" -jsonrpc-core = { version = "17.0", path = "../core" } -jsonrpc-server-utils = { version = "17.0", path = "../server-utils", default-features = false } +jsonrpc-core = { version = "17.1", path = "../core" } +jsonrpc-server-utils = { version = "17.1", path = "../server-utils", default-features = false } parity-tokio-ipc = "0.8" parking_lot = "0.11.0" diff --git a/pubsub/Cargo.toml b/pubsub/Cargo.toml index 566990b3b..7ecd921c6 100644 --- a/pubsub/Cargo.toml +++ b/pubsub/Cargo.toml @@ -8,11 +8,11 @@ keywords = ["jsonrpc", "json-rpc", "json", "rpc", "macros"] license = "MIT" name = "jsonrpc-pubsub" repository = "https://github.com/paritytech/jsonrpc" -version = "17.0.0" +version = "17.1.0" [dependencies] futures = { version = "0.3", features = ["thread-pool"] } -jsonrpc-core = { version = "17.0", path = "../core" } +jsonrpc-core = { version = "17.1", path = "../core" } lazy_static = "1.4" log = "0.4" parking_lot = "0.11.0" @@ -20,7 +20,8 @@ rand = "0.7" serde = "1.0" [dev-dependencies] -jsonrpc-tcp-server = { version = "17.0", path = "../tcp" } +jsonrpc-tcp-server = { version = "17.1", path = "../tcp" } +serde_json = "1.0" [badges] travis-ci = { repository = "paritytech/jsonrpc", branch = "master"} diff --git a/pubsub/more-examples/Cargo.toml b/pubsub/more-examples/Cargo.toml index b222ba108..8a222242e 100644 --- a/pubsub/more-examples/Cargo.toml +++ b/pubsub/more-examples/Cargo.toml @@ -3,12 +3,12 @@ name = "jsonrpc-pubsub-examples" description = "Examples of Publish-Subscribe extension for jsonrpc." homepage = "https://github.com/paritytech/jsonrpc" repository = "https://github.com/paritytech/jsonrpc" -version = "17.0.0" +version = "17.1.0" authors = ["tomusdrw "] license = "MIT" [dependencies] -jsonrpc-core = { version = "17.0", path = "../../core" } -jsonrpc-pubsub = { version = "17.0", path = "../" } -jsonrpc-ws-server = { version = "17.0", path = "../../ws" } -jsonrpc-ipc-server = { version = "17.0", path = "../../ipc" } +jsonrpc-core = { version = "17.1", path = "../../core" } +jsonrpc-pubsub = { version = "17.1", path = "../" } +jsonrpc-ws-server = { version = "17.1", path = "../../ws" } +jsonrpc-ipc-server = { version = "17.1", path = "../../ipc" } diff --git a/pubsub/src/subscription.rs b/pubsub/src/subscription.rs index 8c02512a4..14e6ddcbb 100644 --- a/pubsub/src/subscription.rs +++ b/pubsub/src/subscription.rs @@ -81,8 +81,11 @@ impl Session { } /// Removes existing subscription. - fn remove_subscription(&self, name: &str, id: &SubscriptionId) { - self.active_subscriptions.lock().remove(&(id.clone(), name.into())); + fn remove_subscription(&self, name: &str, id: &SubscriptionId) -> bool { + self.active_subscriptions + .lock() + .remove(&(id.clone(), name.into())) + .is_some() } } @@ -335,8 +338,11 @@ where }; match (meta.session(), id) { (Some(session), Some(id)) => { - session.remove_subscription(&self.notification, &id); - Box::pin(self.unsubscribe.call(id, Some(meta))) + if session.remove_subscription(&self.notification, &id) { + Box::pin(self.unsubscribe.call(id, Some(meta))) + } else { + Box::pin(future::err(core::Error::invalid_params("Invalid subscription id."))) + } } (Some(_), None) => Box::pin(future::err(core::Error::invalid_params("Expected subscription id."))), _ => Box::pin(future::err(subscriptions_unavailable())), @@ -392,13 +398,36 @@ mod tests { }); // when - session.remove_subscription("test", &id); + let removed = session.remove_subscription("test", &id); drop(session); // then + assert_eq!(removed, true); assert_eq!(called.load(Ordering::SeqCst), false); } + #[test] + fn should_not_remove_subscription_if_invalid() { + // given + let id = SubscriptionId::Number(1); + let called = Arc::new(AtomicBool::new(false)); + let called2 = called.clone(); + let other_session = session().0; + let session = session().0; + session.add_subscription("test", &id, move |id| { + assert_eq!(id, SubscriptionId::Number(1)); + called2.store(true, Ordering::SeqCst); + }); + + // when + let removed = other_session.remove_subscription("test", &id); + drop(session); + + // then + assert_eq!(removed, false); + assert_eq!(called.load(Ordering::SeqCst), true); + } + #[test] fn should_unregister_in_case_of_collision() { // given @@ -485,40 +514,86 @@ mod tests { }); } - #[derive(Clone, Default)] - struct Metadata; + #[derive(Clone)] + struct Metadata(Arc); impl core::Metadata for Metadata {} impl PubSubMetadata for Metadata { fn session(&self) -> Option> { - Some(Arc::new(session().0)) + Some(self.0.clone()) + } + } + impl Default for Metadata { + fn default() -> Self { + Self(Arc::new(session().0)) } } #[test] fn should_subscribe() { // given - let called = Arc::new(AtomicBool::new(false)); - let called2 = called.clone(); let (subscribe, _) = new_subscription( "test".into(), - move |params, _meta, _subscriber| { + move |params, _meta, subscriber: Subscriber| { assert_eq!(params, core::Params::None); - called2.store(true, Ordering::SeqCst); + let _sink = subscriber.assign_id(SubscriptionId::Number(5)).unwrap(); }, |_id, _meta| async { Ok(core::Value::Bool(true)) }, ); - let meta = Metadata; // when + let meta = Metadata::default(); let result = subscribe.call(core::Params::None, meta); // then - assert_eq!(called.load(Ordering::SeqCst), true); + assert_eq!(futures::executor::block_on(result), Ok(serde_json::json!(5))); + } + + #[test] + fn should_unsubscribe() { + // given + const SUB_ID: u64 = 5; + let (subscribe, unsubscribe) = new_subscription( + "test".into(), + move |params, _meta, subscriber: Subscriber| { + assert_eq!(params, core::Params::None); + let _sink = subscriber.assign_id(SubscriptionId::Number(SUB_ID)).unwrap(); + }, + |_id, _meta| async { Ok(core::Value::Bool(true)) }, + ); + + // when + let meta = Metadata::default(); + futures::executor::block_on(subscribe.call(core::Params::None, meta.clone())).unwrap(); + let result = unsubscribe.call(core::Params::Array(vec![serde_json::json!(SUB_ID)]), meta); + + // then + assert_eq!(futures::executor::block_on(result), Ok(serde_json::json!(true))); + } + + #[test] + fn should_not_unsubscribe_if_invalid() { + // given + const SUB_ID: u64 = 5; + let (subscribe, unsubscribe) = new_subscription( + "test".into(), + move |params, _meta, subscriber: Subscriber| { + assert_eq!(params, core::Params::None); + let _sink = subscriber.assign_id(SubscriptionId::Number(SUB_ID)).unwrap(); + }, + |_id, _meta| async { Ok(core::Value::Bool(true)) }, + ); + + // when + let meta = Metadata::default(); + futures::executor::block_on(subscribe.call(core::Params::None, meta.clone())).unwrap(); + let result = unsubscribe.call(core::Params::Array(vec![serde_json::json!(SUB_ID + 1)]), meta); + + // then assert_eq!( futures::executor::block_on(result), Err(core::Error { - code: core::ErrorCode::ServerError(-32091), - message: "Subscription rejected".into(), + code: core::ErrorCode::InvalidParams, + message: "Invalid subscription id.".into(), data: None, }) ); diff --git a/server-utils/Cargo.toml b/server-utils/Cargo.toml index 4adbda3c6..aacbce4f0 100644 --- a/server-utils/Cargo.toml +++ b/server-utils/Cargo.toml @@ -8,13 +8,13 @@ keywords = ["jsonrpc", "json-rpc", "json", "rpc", "serde"] license = "MIT" name = "jsonrpc-server-utils" repository = "https://github.com/paritytech/jsonrpc" -version = "17.0.0" +version = "17.1.0" [dependencies] bytes = "0.5" futures = "0.3" globset = "0.4" -jsonrpc-core = { version = "17.0", path = "../core" } +jsonrpc-core = { version = "17.1", path = "../core" } lazy_static = "1.1.0" log = "0.4" tokio = { version = "0.2", features = ["rt-threaded", "io-driver", "io-util", "time", "tcp"] } diff --git a/stdio/Cargo.toml b/stdio/Cargo.toml index ba8725c71..8c907431f 100644 --- a/stdio/Cargo.toml +++ b/stdio/Cargo.toml @@ -7,11 +7,11 @@ homepage = "https://github.com/paritytech/jsonrpc" license = "MIT" name = "jsonrpc-stdio-server" repository = "https://github.com/paritytech/jsonrpc" -version = "17.0.0" +version = "17.1.0" [dependencies] futures = "0.3" -jsonrpc-core = { version = "17.0", path = "../core" } +jsonrpc-core = { version = "17.1", path = "../core" } log = "0.4" tokio = { version = "0.2", features = ["io-std", "io-driver", "io-util"] } tokio-util = { version = "0.3", features = ["codec"] } diff --git a/tcp/Cargo.toml b/tcp/Cargo.toml index 990ef7816..a25777300 100644 --- a/tcp/Cargo.toml +++ b/tcp/Cargo.toml @@ -7,11 +7,11 @@ homepage = "https://github.com/paritytech/jsonrpc" license = "MIT" name = "jsonrpc-tcp-server" repository = "https://github.com/paritytech/jsonrpc" -version = "17.0.0" +version = "17.1.0" [dependencies] -jsonrpc-core = { version = "17.0", path = "../core" } -jsonrpc-server-utils = { version = "17.0", path = "../server-utils" } +jsonrpc-core = { version = "17.1", path = "../core" } +jsonrpc-server-utils = { version = "17.1", path = "../server-utils" } log = "0.4" parking_lot = "0.11.0" tower-service = "0.3" diff --git a/test/Cargo.toml b/test/Cargo.toml index 2dc6cfedd..bfe2c061f 100644 --- a/test/Cargo.toml +++ b/test/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "jsonrpc-test" description = "Simple test framework for JSON-RPC." -version = "17.0.0" +version = "17.1.0" authors = ["Tomasz Drwięga "] license = "MIT" homepage = "https://github.com/paritytech/jsonrpc" @@ -10,9 +10,9 @@ documentation = "https://docs.rs/jsonrpc-test/" edition = "2018" [dependencies] -jsonrpc-core = { version = "17.0", path = "../core" } -jsonrpc-core-client = { version = "17.0", path = "../core-client" } -jsonrpc-pubsub = { version = "17.0", path = "../pubsub" } +jsonrpc-core = { version = "17.1", path = "../core" } +jsonrpc-core-client = { version = "17.1", path = "../core-client" } +jsonrpc-pubsub = { version = "17.1", path = "../pubsub" } log = "0.4" serde = "1.0" serde_json = "1.0" @@ -21,5 +21,5 @@ serde_json = "1.0" arbitrary_precision = ["jsonrpc-core-client/arbitrary_precision", "serde_json/arbitrary_precision", "jsonrpc-core/arbitrary_precision"] [dev-dependencies] -jsonrpc-derive = { version = "17.0", path = "../derive" } +jsonrpc-derive = { version = "17.1", path = "../derive" } diff --git a/ws/Cargo.toml b/ws/Cargo.toml index bfbf74237..a03be3f8c 100644 --- a/ws/Cargo.toml +++ b/ws/Cargo.toml @@ -7,12 +7,12 @@ homepage = "https://github.com/paritytech/jsonrpc" license = "MIT" name = "jsonrpc-ws-server" repository = "https://github.com/paritytech/jsonrpc" -version = "17.0.0" +version = "17.1.0" [dependencies] futures = "0.3" -jsonrpc-core = { version = "17.0", path = "../core" } -jsonrpc-server-utils = { version = "17.0", path = "../server-utils" } +jsonrpc-core = { version = "17.1", path = "../core" } +jsonrpc-server-utils = { version = "17.1", path = "../server-utils" } log = "0.4" parking_lot = "0.11.0" slab = "0.4"