-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ISSUE-151 and 149: Support Subxt wss connections #153
Merged
Merged
Changes from 5 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
c834dc0
Upgrade to jsonrpsee 0.19.0
Lohann 34b7c70
merge master into bugfix/issue-151-support-wss-connections
Lohann 1b36296
Merge main into bugfix/issue-151-support-wss-connections
Lohann 4e5a265
Implemented Tungstenite using jsonrpcsee traits
Lohann 5258e7a
Fix cargo fmt and clippy warnings
Lohann 78d26d4
Fix requested changes
Lohann fac32a2
Refactor config
Lohann 017be24
Fix clippy warnings
Lohann c950c74
Merge branch 'master' into bugfix/issue-151-support-wss-connections
Lohann 0c0f9c5
Add tls feature flags
Lohann b70c521
temporarily remove self-hosted CI
Lohann File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
mod config; | ||
mod jsonrpsee_client; | ||
mod tungstenite_jsonrpsee; | ||
|
||
pub use config::{RpcClientConfig, WsTransportClient}; | ||
pub use jsonrpsee::client_transport::ws::WsHandshakeError; | ||
use jsonrpsee::core::client::{Client, ClientBuilder}; | ||
pub use jsonrpsee_client::RpcClient; | ||
pub use tungstenite_jsonrpsee::{TungsteniteClient, WsError}; | ||
|
||
pub async fn default_client( | ||
url: &str, | ||
config: Option<RpcClientConfig>, | ||
) -> Result<RpcClient, WsHandshakeError> { | ||
let config = config.unwrap_or_default(); | ||
|
||
let client = match config.client { | ||
WsTransportClient::Auto => { | ||
log::info!("Connecting using Socketto..."); | ||
match build_socketto_client(url).await { | ||
Ok(client) => client, | ||
Err(error) => { | ||
log::warn!("Socketto failed: {}", error); | ||
log::info!("Connecting using Tungstenite..."); | ||
build_tungstenite_client(url, RpcClientConfig::default()).await? | ||
} | ||
} | ||
} | ||
WsTransportClient::Socketto => { | ||
let client = build_socketto_client(url).await?; | ||
log::info!("Connected to {} using Socketto", url); | ||
client | ||
} | ||
Lohann marked this conversation as resolved.
Show resolved
Hide resolved
|
||
WsTransportClient::Tungstenite => { | ||
let client = build_tungstenite_client(url, RpcClientConfig::default()).await?; | ||
log::info!("Connected to {} using Tungstenite", url); | ||
client | ||
} | ||
}; | ||
Ok(RpcClient(client)) | ||
} | ||
|
||
async fn build_socketto_client(uri: &str) -> Result<Client, WsHandshakeError> { | ||
use jsonrpsee::client_transport::ws::WsTransportClientBuilder; | ||
use tokio_tungstenite::tungstenite::http::uri::{Authority, Uri}; | ||
|
||
let mut uri = uri | ||
.parse::<Uri>() | ||
.map_err(|e| WsHandshakeError::Url(e.to_string().into()))?; | ||
let default_port = match uri.scheme().map(|s| s.as_str()) { | ||
Some("ws" | "http") => Some(80), | ||
Some("wss" | "https") => Some(443), | ||
_ => None, | ||
}; | ||
|
||
// Set default port, workaround because jsonrpsee doesn't infer the url port: | ||
// https://github.com/paritytech/jsonrpsee/blob/v0.19.0/client/transport/src/ws/mod.rs#L509-L511 | ||
if let (None, Some(port), Some(authority)) = | ||
(uri.port(), default_port, uri.authority().cloned()) | ||
{ | ||
let new_authority = | ||
Authority::try_from(format!("{}:{}", authority, port)).unwrap_or(authority); | ||
uri = { | ||
let mut parts = uri.clone().into_parts(); | ||
parts.authority = Some(new_authority); | ||
Uri::from_parts(parts).unwrap_or(uri) | ||
}; | ||
} | ||
|
||
let (sender, receiver) = WsTransportClientBuilder::default() | ||
.use_webpki_rustls() | ||
.build(uri) | ||
.await?; | ||
let client = ClientBuilder::default() | ||
.max_buffer_capacity_per_subscription(4096) | ||
.build_with_tokio(sender, receiver); | ||
Ok(client) | ||
} | ||
|
||
async fn build_tungstenite_client( | ||
url: &str, | ||
config: RpcClientConfig, | ||
) -> Result<Client, WsHandshakeError> { | ||
use tide::http::url::Url; | ||
|
||
let url = url | ||
.parse::<Url>() | ||
.map_err(|e| WsHandshakeError::Url(e.to_string().into()))?; | ||
let client = TungsteniteClient::new(url, config) | ||
.await | ||
.map_err(|e| match e { | ||
WsError::Url(error) => WsHandshakeError::Url(error.to_string().into()), | ||
WsError::Io(error) => WsHandshakeError::Io(error), | ||
_ => WsHandshakeError::Url(e.to_string().into()), | ||
})?; | ||
let (sender, receiver) = client.split(); | ||
let client = ClientBuilder::default() | ||
.max_buffer_capacity_per_subscription(4096) | ||
.build_with_tokio(sender, receiver); | ||
Ok(client) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/// Ten megabytes. | ||
pub const TEN_MB_SIZE_BYTES: usize = 10 * 1024 * 1024; | ||
|
||
/// Supported WebSocket transport clients. | ||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] | ||
pub enum WsTransportClient { | ||
/// Auto will try to use Socketto first, if it fails, it will fallback to Tungstenite. | ||
#[default] | ||
Auto, | ||
|
||
/// Socketto is the default WebSocket client for Substrate and Subxt. | ||
/// Whoever have an issue when connecting to some RPC nodes using TLS. | ||
/// https://github.com/paritytech/jsonrpsee/issues/1142 | ||
Socketto, | ||
|
||
/// Tungstenite is the most used stream-based WebSocket Client | ||
/// Use this if you have issues with Socketto. | ||
Tungstenite, | ||
} | ||
|
||
/// Common configuration for Socketto and Tungstenite clients. | ||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
pub struct RpcClientConfig { | ||
/// Supported WebSocket transport clients. | ||
pub client: WsTransportClient, | ||
|
||
/// The target minimum size of the write buffer to reach before writing the data | ||
/// to the underlying stream. | ||
/// The default value is 128 KiB. | ||
pub write_buffer_size: usize, | ||
|
||
/// The max size of the write buffer in bytes. Setting this can provide backpressure | ||
/// in the case the write buffer is filling up due to write errors. | ||
/// The default value is unlimited. | ||
/// | ||
/// Note: Should always be at least [`write_buffer_size + 1 message`](Self::write_buffer_size) | ||
/// and probably a little more depending on error handling strategy. | ||
pub max_write_buffer_size: usize, | ||
|
||
/// The maximum size of a message. `None` means no size limit. The default value is 10 MiB | ||
/// which should be reasonably big for all normal use-cases but small enough to prevent | ||
/// memory eating by a malicious user. | ||
pub max_message_size: Option<usize>, | ||
|
||
/// The maximum size of a single message frame. `None` means no size limit. The limit is for | ||
/// frame payload NOT including the frame header. The default value is 16 MiB which should | ||
/// be reasonably big for all normal use-cases but small enough to prevent memory eating | ||
/// by a malicious user. | ||
pub max_frame_size: Option<usize>, | ||
|
||
/// Whether to accept unmasked frames from the peer. The default value is `false`. | ||
/// from the client. According to the RFC 6455, the server must close the | ||
/// connection to the client in such cases, however it seems like there are | ||
/// some popular libraries that are sending unmasked frames, ignoring the RFC. | ||
/// By default this option is set to `false`, i.e. according to RFC 6455. | ||
/// | ||
/// OBS: not supported for Socketto client. | ||
pub accept_unmasked_frames: bool, | ||
} | ||
|
||
impl Default for RpcClientConfig { | ||
fn default() -> Self { | ||
Self { | ||
client: WsTransportClient::Auto, | ||
write_buffer_size: 128 * 1024, | ||
max_write_buffer_size: usize::MAX, | ||
max_message_size: Some(TEN_MB_SIZE_BYTES), | ||
max_frame_size: Some(16 << 20), | ||
accept_unmasked_frames: false, | ||
} | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed the minor tag from a few crates because it allows cargo to solve and get the latest minor version, so we don't have to update it manually every time.