tab_websocket/
lib.rs

1use async_tungstenite::{
2    tokio::{connect_async, TokioAdapter},
3    WebSocketStream,
4};
5use serde::{de::DeserializeOwned, Serialize};
6
7use tokio::net::TcpStream;
8
9use auth::AuthHandler;
10
11use message::listener::RequestMetadata;
12use resource::listener::WebsocketAuthToken;
13use tungstenite::{handshake::client::Request, Message};
14mod auth;
15pub mod bus;
16mod common;
17pub mod message;
18pub mod resource;
19pub mod service;
20
21pub type WebsocketConnection = WebSocketStream<TokioAdapter<TcpStream>>;
22
23/// Connects to the provided URL, with no authentication token
24pub async fn connect(url: String) -> Result<WebsocketConnection, tungstenite::Error> {
25    let tuple = connect_async(url).await?;
26    Ok(tuple.0)
27}
28
29/// Connects to the provided URL, given an authentication token
30pub async fn connect_authorized(
31    url: String,
32    token: String,
33) -> Result<WebsocketConnection, tungstenite::Error> {
34    let request = Request::builder()
35        .uri(url)
36        .header("Authorization", token.trim())
37        .body(())?;
38
39    let (stream, _resp) = connect_async(request).await?;
40    Ok(stream)
41}
42
43/// Binds to the TCP stream as a server, requring the auth token, and capturing request metadata via a lifeline request.
44pub async fn bind(
45    tcp: TcpStream,
46    auth_token: WebsocketAuthToken,
47    request_metadata: lifeline::request::Request<(), RequestMetadata>,
48) -> Result<WebsocketConnection, tungstenite::Error> {
49    let auth = AuthHandler::with_metadata(auth_token, Some(request_metadata));
50    async_tungstenite::tokio::accept_hdr_async(tcp, auth).await
51}
52
53/// Decodes the bincode-serialized message
54pub fn decode<T: DeserializeOwned>(
55    message: Result<tungstenite::Message, tungstenite::Error>,
56) -> anyhow::Result<T> {
57    let message = message?;
58    let data = bincode::deserialize::<T>(message.into_data().as_slice())?;
59    Ok(data)
60}
61
62/// Encodes the message into a bincode-serialized tungstenite message
63pub fn encode<T: Serialize>(message: T) -> anyhow::Result<tungstenite::Message> {
64    let message = bincode::serialize(&message)?;
65    Ok(Message::Binary(message))
66}