shuttle: performed last needed changes to support build for shuttle deployment

This commit is contained in:
Patryk Hegenberg 2024-04-26 17:53:50 +02:00
parent ce1f80cd4f
commit 6fd67f5f4e
8 changed files with 43 additions and 65 deletions

2
Cargo.lock generated
View file

@ -405,7 +405,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
[[package]] [[package]]
name = "caesar" name = "caesar-transfer-iu"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"aes-gcm", "aes-gcm",

View file

@ -1,5 +1,5 @@
[package] [package]
name = "caesar" name = "caesar-transfer-iu"
version = "0.0.1" version = "0.0.1"
edition = "2021" edition = "2021"
build = "src/build.rs" build = "src/build.rs"
@ -9,6 +9,10 @@ authors = ["Manuel Keidel", "Patryk Hegenberg", "Krzysztof Stankiewicz"]
name = "caesar" name = "caesar"
path = "src/main.rs" path = "src/main.rs"
[[bin]]
name = "caesar-transfer-iu"
path = "src/shuttle.rs"
[dependencies] [dependencies]
futures-util = "0.3" futures-util = "0.3"
tungstenite = "0.21.0" tungstenite = "0.21.0"
@ -40,8 +44,8 @@ local-ip-address = "0.6.1"
axum-extra = { version = "0.9.3", features = ["typed-header"] } axum-extra = { version = "0.9.3", features = ["typed-header"] }
headers = "0.4" headers = "0.4"
tower = { version = "0.4", features = ["util"] } tower = { version = "0.4", features = ["util"] }
shuttle-axum = { version = "0.44.0", optional = true } shuttle-axum = { version = "0.44.0" }
shuttle-runtime = { version = "0.44.0", optional = true } shuttle-runtime = { version = "0.44.0" }
dotenvy = "0.15.7" dotenvy = "0.15.7"
[build-dependencies] [build-dependencies]

View file

@ -1,12 +1,6 @@
use crate::cli::args::Args; use crate::cli::args::Args;
#[cfg(not(feature = "shuttle"))]
use dotenv::dotenv; use dotenv::dotenv;
#[cfg(feature = "shuttle")]
use dotenvy::dotenv;
#[cfg(feature = "shuttle")]
use shuttle_axum::ShuttleAxum;
use tracing::error; use tracing::error;
#[cfg(not(feature = "shuttle"))]
use tracing_subscriber::filter::EnvFilter; use tracing_subscriber::filter::EnvFilter;
pub mod cli; pub mod cli;
@ -15,7 +9,6 @@ pub mod relay;
pub mod sender; pub mod sender;
pub mod shared; pub mod shared;
#[cfg(not(feature = "shuttle"))]
#[tokio::main] #[tokio::main]
// This is the entrypoint of caesar. // This is the entrypoint of caesar.
// The #[tokio::main] attribute is required for any async code, and it // The #[tokio::main] attribute is required for any async code, and it
@ -42,29 +35,3 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
// Return an Ok result, which just means that our program exited successfully. // Return an Ok result, which just means that our program exited successfully.
Ok(()) Ok(())
} }
#[cfg(feature = "shuttle")]
#[shuttle_runtime::main]
async fn main() -> ShuttleAxum {
dotenv().ok();
let app_host = env::var("APP_HOST").unwrap_or("0.0.0.0".to_string());
let app_port = env::var("APP_PORT").unwrap_or("8000".to_string());
// Log information about the server's configuration.
debug!("Server configured to accept connections on host {app_host}...",);
debug!("Server configured to listen connections on port {app_port}...",);
// Create a new server data structure.
let server = server::Server::new();
// Set up the application routes.
let app = Router::new()
.route("/ws", get(ws_handler))
.with_state(server)
.layer(SecureClientIpSource::ConnectInfo.into_extension())
.layer(
TraceLayer::new_for_http()
.make_span_with(DefaultMakeSpan::default().include_headers(true)),
);
Ok(app.into())
}

View file

@ -44,10 +44,8 @@ use tokio_tungstenite::{
tungstenite::{client::IntoClientRequest, http::HeaderValue}, tungstenite::{client::IntoClientRequest, http::HeaderValue},
}; };
use tracing::error; use tracing::error;
use url::Url;
pub async fn start_receiver(relay: &str, name: &str) { pub async fn start_receiver(relay: &str, name: &str) {
let argument = name;
let Ok(mut request) = relay.into_client_request() else { let Ok(mut request) = relay.into_client_request() else {
println!("Error: Failed to create request."); println!("Error: Failed to create request.");
return; return;
@ -66,17 +64,8 @@ pub async fn start_receiver(relay: &str, name: &str) {
return; return;
}; };
// If the URL is valid and contains an invite code fragment, // The start function is defined in the
// extract it and pass it to the receiver::client::start
// function. The start function is defined in the
// receiver::client module and is the function that interacts with // receiver::client module and is the function that interacts with
// the server to receive files. // the server to receive files.
if let Ok(url) = Url::parse(argument) { receiver::start(socket, name).await
let Some(fragment) = url.fragment() else {
error!("Error: Missing invite code fragment in url.");
return;
};
receiver::start(socket, fragment).await
}
} }

View file

@ -17,12 +17,11 @@
/// host and port, it logs an error and exits. /// host and port, it logs an error and exits.
pub mod server; pub mod server;
use axum::{ use axum::{
extract::{ws::WebSocket, ConnectInfo, State, WebSocketUpgrade}, extract::{ws::WebSocket, State, WebSocketUpgrade},
response::IntoResponse, response::IntoResponse,
routing::get, routing::get,
Router, Router,
}; };
use axum_client_ip::SecureClientIpSource;
use futures_util::StreamExt; use futures_util::StreamExt;
use std::{env, net::SocketAddr, sync::Arc}; use std::{env, net::SocketAddr, sync::Arc};
@ -32,7 +31,7 @@ use tokio::{
sync::{Mutex, RwLock}, sync::{Mutex, RwLock},
}; };
use tower_http::trace::{DefaultMakeSpan, TraceLayer}; use tower_http::trace::{DefaultMakeSpan, TraceLayer};
use tracing::{debug, error, info}; use tracing::{debug, error, info, warn};
use self::server::Client; use self::server::Client;
@ -97,7 +96,6 @@ pub async fn start_ws(port: Option<&i32>, listen_addr: Option<&String>) {
let app = Router::new() let app = Router::new()
.route("/ws", get(ws_handler)) .route("/ws", get(ws_handler))
.with_state(server) .with_state(server)
.layer(SecureClientIpSource::ConnectInfo.into_extension())
.layer( .layer(
TraceLayer::new_for_http() TraceLayer::new_for_http()
.make_span_with(DefaultMakeSpan::default().include_headers(true)), .make_span_with(DefaultMakeSpan::default().include_headers(true)),
@ -157,15 +155,15 @@ pub async fn start_ws(port: Option<&i32>, listen_addr: Option<&String>) {
/// `handle_message` function is defined in the `src/relay/client.rs` file. The /// `handle_message` function is defined in the `src/relay/client.rs` file. The
/// `handle_message` function handles incoming messages from the client and /// `handle_message` function handles incoming messages from the client and
/// takes care of sending the appropriate response back to the client. /// takes care of sending the appropriate response back to the client.
async fn ws_handler( pub async fn ws_handler(
ws: WebSocketUpgrade, ws: WebSocketUpgrade,
State(shared_state): State<Arc<RwLock<server::Server>>>, State(shared_state): State<Arc<RwLock<server::Server>>>,
ConnectInfo(addr): ConnectInfo<SocketAddr>, // ConnectInfo(addr): ConnectInfo<SocketAddr>,
) -> impl IntoResponse { ) -> impl IntoResponse {
debug!("Got Request on Websocket route"); debug!("Got Request on Websocket route");
debug!("WebSocket connection established from:{}", addr.to_string()); // debug!("WebSocket connection established from:{}", addr.to_string());
debug!("Upgrading Connection"); debug!("Upgrading Connection");
ws.on_upgrade(move |socket| handle_socket(socket, addr, shared_state)) ws.on_upgrade(move |socket| handle_socket(socket, shared_state))
} }
/// This function is called when a new WebSocket connection is established. /// This function is called when a new WebSocket connection is established.
@ -203,7 +201,7 @@ async fn ws_handler(
/// `Client` object that it created. The `handle_close` method is defined in the /// `Client` object that it created. The `handle_close` method is defined in the
/// `src/relay/client.rs` file. The `handle_close` method handles the close event /// `src/relay/client.rs` file. The `handle_close` method handles the close event
/// from the client. /// from the client.
async fn handle_socket(socket: WebSocket, who: SocketAddr, rooms: Arc<RwLock<server::Server>>) { async fn handle_socket(socket: WebSocket, rooms: Arc<RwLock<server::Server>>) {
let (sender, mut receiver) = socket.split(); let (sender, mut receiver) = socket.split();
let sender = Arc::new(Mutex::new(sender)); let sender = Arc::new(Mutex::new(sender));
@ -214,7 +212,7 @@ async fn handle_socket(socket: WebSocket, who: SocketAddr, rooms: Arc<RwLock<ser
client.handle_message(&rooms, message).await; client.handle_message(&rooms, message).await;
} }
Err(error) => { Err(error) => {
error!("Failed to read message from client {}: {}", who, error); warn!("Failed to read message from client: {}", error);
break; break;
} }
} }

View file

@ -28,7 +28,6 @@ const DESTINATION: u8 = 1;
const NONCE_SIZE: usize = 12; const NONCE_SIZE: usize = 12;
const MAX_CHUNK_SIZE: isize = u16::MAX as isize; const MAX_CHUNK_SIZE: isize = u16::MAX as isize;
const DELAY: Duration = Duration::from_millis(750); const DELAY: Duration = Duration::from_millis(750);
const URL: &str = "https://0.0.0.0:8000/#";
/// A file that is to be sent. /// A file that is to be sent.
/// ///
@ -120,7 +119,7 @@ struct Context {
/// message to the console with the URL. /// message to the console with the URL.
fn on_create_room(context: &Context, id: String) -> Status { fn on_create_room(context: &Context, id: String) -> Status {
let base64 = general_purpose::STANDARD.encode(&context.hmac); let base64 = general_purpose::STANDARD.encode(&context.hmac);
let url = format!("{}{}-{}", URL, id, base64); let url = format!("{}-{}", id, base64);
// Print a newline to the console to separate the output from the command // Print a newline to the console to separate the output from the command
// line. // line.

View file

@ -47,8 +47,6 @@ use tokio_tungstenite::{
}; };
use tracing::{debug, error}; use tracing::{debug, error};
// const ORIGIN: &str = "ws://0.0.0.0:8000/ws";
pub async fn start_sender(relay: &str, files: &[String]) { pub async fn start_sender(relay: &str, files: &[String]) {
let Ok(mut request) = relay.into_client_request() else { let Ok(mut request) = relay.into_client_request() else {
println!("Error: Failed to create request."); println!("Error: Failed to create request.");
@ -59,7 +57,7 @@ pub async fn start_sender(relay: &str, files: &[String]) {
.headers_mut() .headers_mut()
.insert("Origin", HeaderValue::from_str(relay).unwrap()); .insert("Origin", HeaderValue::from_str(relay).unwrap());
debug!("Attempting to connect..."); debug!("Attempting to connect to {relay}...");
let Ok((socket, _)) = connect_async(request).await else { let Ok((socket, _)) = connect_async(request).await else {
error!("Error: Failed to connect."); error!("Error: Failed to connect.");

23
src/shuttle.rs Normal file
View file

@ -0,0 +1,23 @@
use axum::{routing::get, Router};
use axum_client_ip::SecureClientIpSource;
use relay::server;
use shuttle_axum::ShuttleAxum;
pub mod receiver;
pub mod relay;
pub mod sender;
pub mod shared;
#[shuttle_runtime::main]
async fn axum() -> ShuttleAxum {
// Create a new server data structure.
let server = server::Server::new();
// Set up the application routes.
let app = Router::new()
.route("/ws", get(relay::ws_handler))
.with_state(server)
.layer(SecureClientIpSource::ConnectInfo.into_extension());
Ok(app.into())
}