c410-f3r / wtx

A collection of different transport implementations and related tools focused primarily on web technologies.
https://c410-f3r.github.io/wtx
Apache License 2.0
191 stars 6 forks source link

websocket tls usage. #241

Closed llvm-x86 closed 1 month ago

llvm-x86 commented 1 month ago

How should I properly use a standard tls stream for https endpoints?

Connected to ("ws.bitskins.com", 443)
connecting to "ws.bitskins.com"
thread 'main' panicked at src/ws_trader.rs:33:10:
called `Result::unwrap()` on an `Err` value: IoError(Custom { kind: InvalidData, error: InvalidCertificate(UnknownIssuer) })
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
use std::sync::OnceLock;

use tokio::net::TcpStream;
use wtx::{
    misc::{simple_seed, TokioRustlsConnector, Uri, Xorshift64},
    web_socket::{FrameBufferVec, FrameMutVec, OpCode, WebSocketBuffer, WebSocketClient},
};

use crate::{http_client::HttpClient, structs::Listing, telegram::TelegramBot};

pub const LISTED: &str = "listed";
const URL: &str = "wss://ws.bitskins.com";
const WS_AUTH_APIKEY: &str = "WS_AUTH_APIKEY";
const WS_SUB: &str = "WS_SUB";

pub async fn ws_loop(api_key: String) -> wtx::Result<()> {
    let uri = Uri::new(URL);
    let fb = &mut FrameBufferVec::default();
    let tls = TokioRustlsConnector::default();
    let stream = TcpStream::connect(uri.hostname_with_implied_port())
        .await
        .unwrap();
    println!("Connected to {:?}", uri.hostname_with_implied_port());
    println!("connecting to {:?}", uri.hostname());
    let stream = tls
        .connect_without_client_auth(uri.hostname(), stream)
        .await
        .unwrap();

    let mut ws = WebSocketClient::connect(
        (),
        [],
        Xorshift64::from(simple_seed()),
        stream,
        &uri.to_ref(),
        WebSocketBuffer::default(),
        |_| wtx::Result::Ok(()),
    )
    .await?;
}
c410-f3r commented 1 month ago

The client needs a set of valid certificates to connect using TLS. For example, "webpkit-roots" is one crate that provides certificates.

[dependencies]
tokio = { default-features = false, features = ["macros", "net", "rt-multi-thread"], version = "1.0" }
wtx = { default-features = false, features = ["tokio-rustls", "webpki-roots", "web-socket-handshake"], version = "0.21" }
use tokio::net::TcpStream;
use wtx::{
    misc::{simple_seed, TokioRustlsConnector, Uri, Xorshift64},
    web_socket::{FrameBufferVec, OpCode, WebSocketBuffer, WebSocketClient},
};

#[tokio::main]
async fn main() -> wtx::Result<()> {
    let uri = Uri::new("https://echo.websocket.org");
    let tls = TokioRustlsConnector::from_auto()?;
    let stream = TcpStream::connect(uri.hostname_with_implied_port()).await?;
    let tls_stream = tls
        .connect_without_client_auth(uri.hostname(), stream)
        .await?;
    let mut ws = WebSocketClient::connect(
        (),
        [],
        Xorshift64::from(simple_seed()),
        tls_stream,
        &uri.to_ref(),
        WebSocketBuffer::default(),
        |_| wtx::Result::Ok(()),
    )
    .await?;
    let mut fb = FrameBufferVec::default();
    loop {
        let frame = ws.read_frame(&mut fb).await?;
        match (frame.op_code(), frame.text_payload()) {
            (_, Some(elem)) => println!("{elem}"),
            (OpCode::Close, _) => break,
            _ => {}
        }
    }
    Ok(())
}

I will update the documentation to reflect this behaviour but it is worth noting again that wtx is under active development, as such, I don't recommend usage in production environments at the current time.

llvm-x86 commented 1 month ago
tokio = { default-features = false, features = ["macros", "rt-multi-thread", "net"], version = "1.0" }
wtx = {version = "0.21.0", features = ["web-socket", "tokio-rustls", "web-socket-handshake", "webpki-roots", "tokio-rustls"]}

I was using these features and still got the above error. Additionally for the example sent I never successfully connect. I understand crate is under development so I don't want to slow you down. My use-case is listening to one connection so I should write a busy-spinning implementation anyways. Cool repository wish I understood half of what you're doing inside.

warning: `rust-bitskins` (bin "rust-bitskins" test) generated 9 warnings (run `cargo fix --bin "rust-bitskins" --tests` to apply 1 suggestion)
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.87s
     Running unittests src/main.rs (target/debug/deps/rust_bitskins-3cfa4c4e054e0c4e)

running 1 test
#[cfg(test)]
mod test {
    use tokio::net::TcpStream;
    use wtx::{
        misc::{simple_seed, TokioRustlsConnector, Uri, Xorshift64},
        web_socket::{FrameBufferVec, FrameMutVec, OpCode, WebSocketBuffer, WebSocketClient},
    };

    #[tokio::test]
    async fn test_ws() -> wtx::Result<()> {
        let uri = Uri::new("https://echo.websocket.org");
        let tls = TokioRustlsConnector::from_auto()?;
        let stream = TcpStream::connect(uri.hostname_with_implied_port()).await?;
        let tls_stream = tls
            .connect_without_client_auth(uri.hostname(), stream)
            .await?;
        println!("tls stream: {:?}", tls_stream);
        let mut ws = WebSocketClient::connect(
            (),
            [],
            Xorshift64::from(simple_seed()),
            tls_stream,
            &uri.to_ref(),
            WebSocketBuffer::default(),
            |_| wtx::Result::Ok(()),
        )
        .await?;
        println!("Connected to {:?}", uri.hostname_with_implied_port());

        ws.write_frame(&mut FrameMutVec::new_fin(
            &mut FrameBufferVec::default(),
            OpCode::Text,
            b"Hello, world!",
        )?)
        .await?;

        let mut fb = FrameBufferVec::default();
        loop {
            let frame = ws.read_frame(&mut fb).await?;
            match (frame.op_code(), frame.text_payload()) {
                (_, Some(elem)) => println!("{elem}"),
                (OpCode::Close, _) => break,
                _ => {}
            }
        }
        Ok(())
    }
}
llvm-x86 commented 1 month ago

@c410-f3r haha im so sorry i just read the from_auto line zzzzz

c410-f3r commented 1 month ago

Don't worry, wtx is not very intuitive. Hopefully documentation will change things for the better.