backend: refactor proxy code
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
use anyhow::{Result, anyhow};
|
||||
|
||||
use salvo::{
|
||||
prelude::*,
|
||||
proto::quic::BidiStream,
|
||||
webtransport::{self},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tracing::{error, info};
|
||||
|
||||
use crate::{
|
||||
backend,
|
||||
common::{AppError, AppResult},
|
||||
};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct ProxySetupParams {
|
||||
pub stream: backend::Stream,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct ProxySetupResponse {
|
||||
pub cert_hash: [u8; 32],
|
||||
//pub cert_hash: String,
|
||||
}
|
||||
|
||||
async fn setup_webtransport(
|
||||
req: &mut Request,
|
||||
) -> Result<(
|
||||
impl tokio::io::AsyncWrite + Send + Sync + 'static,
|
||||
impl tokio::io::AsyncRead + Send + Sync + 'static,
|
||||
//salvo::webtransport::stream::SendStream<
|
||||
// impl salvo::proto::quic::SendStream<salvo::hyper::body::Bytes>,
|
||||
// salvo::hyper::body::Bytes,
|
||||
//>,
|
||||
//salvo::webtransport::stream::RecvStream<
|
||||
// impl salvo::proto::quic::RecvStream,
|
||||
// salvo::hyper::body::Bytes,
|
||||
//>,
|
||||
)> {
|
||||
let session = req.web_transport_mut().await?;
|
||||
let bidirectional_stream = session
|
||||
.accept_bi()
|
||||
.await?
|
||||
.ok_or(anyhow!("No bidirectional stream"))?;
|
||||
|
||||
if let webtransport::server::AcceptedBi::BidiStream(_, stream) = bidirectional_stream {
|
||||
Ok(stream.split())
|
||||
} else {
|
||||
Err(anyhow!("bidirectional stream was of the wrong type"))
|
||||
}
|
||||
}
|
||||
|
||||
#[craft]
|
||||
impl crate::proxy::Proxy {
|
||||
#[craft(handler)]
|
||||
pub async fn stream_setup(
|
||||
self: ::std::sync::Arc<Self>,
|
||||
body: salvo::oapi::extract::JsonBody<ProxySetupParams>,
|
||||
) -> AppResult<Json<ProxySetupResponse>> {
|
||||
let mut writer = self.stream.write().await;
|
||||
*writer = Some(body.stream.clone());
|
||||
|
||||
info!("Configured proxy with config: {:?}", body.stream);
|
||||
|
||||
Ok(Json(ProxySetupResponse {
|
||||
cert_hash: self.cert_hash,
|
||||
}))
|
||||
}
|
||||
|
||||
#[craft(handler)]
|
||||
pub async fn stream_connect(self: ::std::sync::Arc<Self>, req: &mut Request) -> AppResult<()> {
|
||||
let standard_error = Err(crate::common::AppError {
|
||||
status_code: StatusCode::INTERNAL_SERVER_ERROR,
|
||||
description: "Could not start stream".to_string(),
|
||||
});
|
||||
|
||||
info!("WebTransport connection initiated");
|
||||
let (wt_send, wt_recv) = match setup_webtransport(req).await {
|
||||
Ok(w) => w,
|
||||
Err(e) => {
|
||||
error!("Could not upgrade connection to WebTransport: {e}");
|
||||
return standard_error;
|
||||
}
|
||||
};
|
||||
|
||||
let stream = match self.stream.read().await.clone() {
|
||||
Some(s) => s,
|
||||
None => {
|
||||
error!("Stream has not been configured, cannot connect to server");
|
||||
return Err(AppError {
|
||||
status_code: StatusCode::BAD_REQUEST,
|
||||
description: "Proxy has not been configured yet: THIS IS A BUG".to_string(),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
match super::proxy_main(stream, wt_send, wt_recv).await {
|
||||
Ok(()) => Ok(()),
|
||||
Err(e) => {
|
||||
error!("Proxy main loop failed: {e}");
|
||||
standard_error
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user