diff --git a/src/main.rs b/src/main.rs index ba2e888..b6baa3f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -56,134 +56,169 @@ fn handle(argument: Arc, peer: SocketAddr, stream: &mut TlsStream println!("[{}] [warning] [{peer}] Connection closed by peer", now()), - Ok(l) => match request::Titan::from_bytes(&input[..l]) { - Ok(titan) => { - // init memory pool - let mut data: Vec = Vec::with_capacity(titan.size); - loop { - // read data bytes - let mut input = vec![0; argument.chunk]; - match stream.read(&mut input) { - Ok(0) => { - println!("[{}] [warning] [{peer}] Connection closed by peer", now()) - } - Ok(l) => { - data.extend(&input[..l]); - - // calculate once - let total = data.len(); - - // validate server-side limits - if argument.size.is_some_and(|limit| total > limit) { - const MESSAGE: &str = "Allowed max length limit reached"; - return send( - &response::failure::permanent::BadRequest { - message: Some(MESSAGE.to_string()), + Ok(l) => { + match Request::from_bytes(&input[..l]) { + Ok(request) => { + match request { + Request::Gemini(gemini) => println!("request: {}", gemini.url), // @TODO + Request::Titan(titan) => { + // init memory pool + let mut data: Vec = Vec::with_capacity(titan.size); + loop { + // read data bytes + let mut input = vec![0; argument.chunk]; + match stream.read(&mut input) { + Ok(0) => { + println!( + "[{}] [warning] [{peer}] Connection closed by peer", + now() + ) } - .into_bytes(), - stream, - |result| match result { - Ok(()) => { - println!("[{}] [warning] [{peer}] {MESSAGE}", now()) - } - Err(e) => println!("[{}] [error] [{peer}] {e}", now()), - }, - ); - } + Ok(l) => { + data.extend(&input[..l]); - // all expected data received - if titan.size >= total { - // validate client-side limits - if titan.size > total { - const MESSAGE: &str = "Data size mismatch header declaration"; - return send( - &response::failure::permanent::BadRequest { - message: Some(MESSAGE.to_string()), - } - .into_bytes(), - stream, - |result| match result { - Ok(()) => { - println!("[{}] [warning] [{peer}] {MESSAGE}", now()) - } - Err(e) => println!("[{}] [error] [{peer}] {e}", now()), - }, - ); - } + // calculate once + let total = data.len(); - // @TODO detect/validate/cache mime based on data received - - // success - match storage::Item::create(&argument.directory) { - Ok(mut tmp) => match tmp.file.write(titan.data) { - Ok(_) => match tmp.commit() { - Ok(pmt) => send( - &response::redirect::Permanent { - target: pmt.path.to_str().unwrap().to_owned(), + // validate server-side limits + if argument.size.is_some_and(|limit| total > limit) { + const MESSAGE: &str = + "Allowed max length limit reached"; + return send( + &response::failure::permanent::BadRequest { + message: Some(MESSAGE.to_string()), } .into_bytes(), stream, |result| match result { - Ok(()) => println!( - "[{}] [info] [{peer}] Data saved to {}", - now(), - pmt.path.to_string_lossy() - ), - Err(e) => println!( - "[{}] [warning] [{peer}] {e}", - now() - ), - }, - ), - Err((tmp, e)) => send( - &response::failure::temporary::General { - message: Some( - "Internal server error".to_string(), - ), - } - .into_bytes(), - stream, - |result| { - match result { - Ok(()) => println!( - "[{}] [error] [{peer}] {e}", - now() - ), - Err(e) => println!( - "[{}] [error] [{peer}] {e}", - now() - ), - }; - if let Err(e) = tmp.delete() { - println!( - "[{}] [error] [{peer}] {e}", - now() - ); - } - }, - ), - }, - Err(e) => send( - &response::failure::temporary::General { - message: Some("Internal server error".to_string()), - } - .into_bytes(), - stream, - |result| { - match result { Ok(()) => { - println!("[{}] [error] [{peer}] {e}", now()) + println!( + "[{}] [warning] [{peer}] {MESSAGE}", + now() + ) } Err(e) => { println!("[{}] [error] [{peer}] {e}", now()) } - }; - if let Err(e) = tmp.delete() { - println!("[{}] [error] [{peer}] {e}", now()); - } - }, - ), - }, + }, + ); + } + + // all expected data received + if titan.size >= total { + // validate client-side limits + if titan.size > total { + const MESSAGE: &str = + "Data size mismatch header declaration"; + return send( + &response::failure::permanent::BadRequest { + message: Some(MESSAGE.to_string()), + } + .into_bytes(), + stream, + |result| match result { + Ok(()) => { + println!( + "[{}] [warning] [{peer}] {MESSAGE}", + now() + ) + } + Err(e) => println!( + "[{}] [error] [{peer}] {e}", + now() + ), + }, + ); + } + + // @TODO detect/validate/cache mime based on data received + + // success + match storage::Item::create(&argument.directory) { + Ok(mut tmp) => match tmp.file.write(titan.data) { + Ok(_) => match tmp.commit() { + Ok(pmt) => send( + &response::redirect::Permanent { + target: pmt.path.to_str().unwrap().to_owned(), + } + .into_bytes(), + stream, + |result| match result { + Ok(()) => println!( + "[{}] [info] [{peer}] Data saved to {}", + now(), + pmt.path.to_string_lossy() + ), + Err(e) => println!( + "[{}] [warning] [{peer}] {e}", + now() + ), + }, + ), + Err((tmp, e)) => send( + &response::failure::temporary::General { + message: Some( + "Internal server error".to_string(), + ), + } + .into_bytes(), + stream, + |result| { + match result { + Ok(()) => println!( + "[{}] [error] [{peer}] {e}", + now() + ), + Err(e) => println!( + "[{}] [error] [{peer}] {e}", + now() + ), + }; + if let Err(e) = tmp.delete() { + println!( + "[{}] [error] [{peer}] {e}", + now() + ); + } + }, + ), + }, + Err(e) => send( + &response::failure::temporary::General { + message: Some("Internal server error".to_string()), + } + .into_bytes(), + stream, + |result| { + match result { + Ok(()) => { + println!("[{}] [error] [{peer}] {e}", now()) + } + Err(e) => { + println!("[{}] [error] [{peer}] {e}", now()) + } + }; + if let Err(e) = tmp.delete() { + println!("[{}] [error] [{peer}] {e}", now()); + } + }, + ), + }, + Err(e) => send( + &response::failure::temporary::General { + message: Some("Internal server error".to_string()), + } + .into_bytes(), + stream, + |result| match result { + Ok(()) => println!("[{}] [error] [{peer}] {e}", now()), + Err(e) => println!("[{}] [error] [{peer}] {e}", now()), + }, + ), + } + break; + } + } Err(e) => send( &response::failure::temporary::General { message: Some("Internal server error".to_string()), @@ -196,35 +231,23 @@ fn handle(argument: Arc, peer: SocketAddr, stream: &mut TlsStream send( - &response::failure::temporary::General { - message: Some("Internal server error".to_string()), - } - .into_bytes(), - stream, - |result| match result { - Ok(()) => println!("[{}] [error] [{peer}] {e}", now()), - Err(e) => println!("[{}] [error] [{peer}] {e}", now()), - }, - ), } } + Err(e) => send( + &response::failure::temporary::General { + message: Some("Internal server error".to_string()), + } + .into_bytes(), + stream, + |result| match result { + Ok(()) => println!("[{}] [error] [{peer}] {e}", now()), + Err(e) => println!("[{}] [error] [{peer}] {e}", now()), + }, + ), } - Err(e) => send( - &response::failure::temporary::General { - message: Some("Internal server error".to_string()), - } - .into_bytes(), - stream, - |result| match result { - Ok(()) => println!("[{}] [error] [{peer}] {e}", now()), - Err(e) => println!("[{}] [error] [{peer}] {e}", now()), - }, - ), - }, + } Err(e) => send( &response::failure::temporary::General { message: Some("Internal server error".to_string()),