Skip to content

Broken "reference" from framed::WsConfig to crate::WsConfig #5976

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

Open
jmg-duarte opened this issue Apr 7, 2025 · 3 comments
Open

Broken "reference" from framed::WsConfig to crate::WsConfig #5976

jmg-duarte opened this issue Apr 7, 2025 · 3 comments

Comments

@jmg-duarte
Copy link

The doc for framed::WsConfig states:

/// A Websocket transport whose output type is a [`Stream`] and [`Sink`] of
/// frame payloads which does not implement [`AsyncRead`] or
/// [`AsyncWrite`]. See [`crate::Config`] if you require the latter.
#[deprecated = "Use `Config` instead"]
pub type WsConfig<T> = Config<T>;

Yet, when checking the config, nothing mentions the framed vs non-framed

/// A Websocket transport.
///
/// DO NOT wrap this transport with a DNS transport if you want Secure Websockets to work.
///
/// A Secure Websocket transport needs to wrap DNS transport to resolve domain names after
/// they are checked against the remote certificates. Use a combination of DNS and TCP transports
/// to build a Secure Websocket transport.
///
/// If you don't need Secure Websocket's support, use a plain TCP transport as an inner transport.
///
/// # Dependencies
///
/// This transport requires the `zlib` shared library to be installed on the system.
///
/// Future releases might lift this requirement, see <https://github.com/paritytech/soketto/issues/72>.
///
/// # Examples
///
/// Secure Websocket transport:
///
/// ```
/// # use futures::future;
/// # use libp2p_core::{transport::ListenerId, Transport};
/// # use libp2p_dns as dns;
/// # use libp2p_tcp as tcp;
/// # use libp2p_websocket as websocket;
/// # use std::pin::Pin;
/// #
/// # #[async_std::main]
/// # async fn main() {
///
/// let mut transport = websocket::Config::new(
/// dns::async_std::Transport::system(tcp::async_io::Transport::new(tcp::Config::default()))
/// .await
/// .unwrap(),
/// );
///
/// let rcgen::CertifiedKey {
/// cert: rcgen_cert,
/// key_pair,
/// } = rcgen::generate_simple_self_signed(vec!["localhost".to_string()]).unwrap();
/// let priv_key = websocket::tls::PrivateKey::new(key_pair.serialize_der());
/// let cert = websocket::tls::Certificate::new(rcgen_cert.der().to_vec());
/// transport.set_tls_config(websocket::tls::Config::new(priv_key, vec![cert]).unwrap());
///
/// let id = transport
/// .listen_on(
/// ListenerId::next(),
/// "/ip4/127.0.0.1/tcp/0/tls/ws".parse().unwrap(),
/// )
/// .unwrap();
///
/// let addr = future::poll_fn(|cx| Pin::new(&mut transport).poll(cx))
/// .await
/// .into_new_address()
/// .unwrap();
/// println!("Listening on {addr}");
///
/// # }
/// ```
///
/// Plain Websocket transport:
///
/// ```
/// # use futures::future;
/// # use libp2p_core::{transport::ListenerId, Transport};
/// # use libp2p_dns as dns;
/// # use libp2p_tcp as tcp;
/// # use libp2p_websocket as websocket;
/// # use std::pin::Pin;
/// #
/// # #[async_std::main]
/// # async fn main() {
///
/// let mut transport =
/// websocket::Config::new(tcp::async_io::Transport::new(tcp::Config::default()));
///
/// let id = transport
/// .listen_on(
/// ListenerId::next(),
/// "/ip4/127.0.0.1/tcp/0/ws".parse().unwrap(),
/// )
/// .unwrap();
///
/// let addr = future::poll_fn(|cx| Pin::new(&mut transport).poll(cx))
/// .await
/// .into_new_address()
/// .unwrap();
/// println!("Listening on {addr}");
///
/// # }
/// ```
#[deprecated = "Use `Config` instead"]
pub type WsConfig<Transport> = Config<Transport>;
#[derive(Debug)]
pub struct Config<T: Transport>
where
T: Transport,
T::Output: AsyncRead + AsyncWrite + Send + Unpin + 'static,
{
transport: libp2p_core::transport::map::Map<framed::Config<T>, WrapperFn<T::Output>>,
}

@elenaf9
Copy link
Member

elenaf9 commented Apr 10, 2025

The phrasing is maybe a bit confusing. What it means is that you should use crate::Config variant (which is actually just a wrapper of framed::WsConfig) if you require the output to implement Async{Read,Write}. See description of #1150:

Actually two transports are implemented, one in the framed module whose output implements Stream and Sink, but not AsyncRead or AsyncWrite, and on top of that another transport which merely wraps the output of the former in a RwStreamSink to produce an output type which implements AsyncRead and AsyncWrite. The output of the framed transport produces and consumes just bytes which correspond to the actual application data in a websocket frame. (See #1103 for details.)

If you think that this could be phrased better a PR would be appreciated!

@jmg-duarte
Copy link
Author

I'd be more than happy to help but it's not entirely clear to me where/how framed vs non-framed is useful. I found this out while trying to figure out why my Swarm wasn't working even though it had (from what I could tell) the same configuration as another working one.

The gist linked in #1150 is also "dead" so it's slightly harder to try and figure it out

@elenaf9
Copy link
Member

elenaf9 commented Apr 30, 2025

I'd be more than happy to help but it's not entirely clear to me where/how framed vs non-framed is useful.

I haven't done much with that transport myself, but generally most user want to use the crate::WsConfig one because it just let's you read and write a stream of bytes. From what I can tell it only sends and handle binary frames and text frames (see RFC6455)

The framed::WsConfig exposes all the actual websocket frames, including control frames like ping/pong frames etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants