mirror of
https://github.com/YGGverse/titanit.git
synced 2026-03-31 17:15:30 +00:00
prevent server fault on handshake issues, fix size conditions, begin response implementation
This commit is contained in:
parent
5e2b90a39e
commit
61f5e22da3
1 changed files with 71 additions and 46 deletions
59
src/main.rs
59
src/main.rs
|
|
@ -4,11 +4,12 @@ mod storage;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use argument::Argument;
|
use argument::Argument;
|
||||||
|
|
||||||
use native_tls::{Identity, TlsAcceptor, TlsStream};
|
use native_tls::{HandshakeError, Identity, TlsAcceptor, TlsStream};
|
||||||
use std::{
|
use std::{
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{Read, Write},
|
io::{Read, Write},
|
||||||
net::{SocketAddr, TcpListener, TcpStream},
|
net::{SocketAddr, TcpListener, TcpStream},
|
||||||
|
os::unix::fs::FileExt,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
thread,
|
thread,
|
||||||
time::{SystemTime, UNIX_EPOCH},
|
time::{SystemTime, UNIX_EPOCH},
|
||||||
|
|
@ -40,8 +41,8 @@ fn main() -> Result<()> {
|
||||||
thread::spawn({
|
thread::spawn({
|
||||||
let argument = argument.clone();
|
let argument = argument.clone();
|
||||||
let peer = stream.peer_addr()?;
|
let peer = stream.peer_addr()?;
|
||||||
let mut stream = acceptor.accept(stream)?;
|
let connection = acceptor.accept(stream);
|
||||||
move || handle(argument, peer, &mut stream)
|
move || handle(argument, peer, connection)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Err(e) => println!("[{}] [error] {e}", now()),
|
Err(e) => println!("[{}] [error] {e}", now()),
|
||||||
|
|
@ -50,23 +51,29 @@ fn main() -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle(argument: Arc<Argument>, peer: SocketAddr, stream: &mut TlsStream<TcpStream>) {
|
fn handle(
|
||||||
|
argument: Arc<Argument>,
|
||||||
|
peer: SocketAddr,
|
||||||
|
connection: Result<TlsStream<TcpStream>, HandshakeError<TcpStream>>,
|
||||||
|
) {
|
||||||
use titanite::*;
|
use titanite::*;
|
||||||
//println!("[{}] [info] [{peer}] New connection", now());
|
//println!("[{}] [info] [{peer}] New connection", now());
|
||||||
|
match connection {
|
||||||
|
Ok(mut stream) => {
|
||||||
let mut input = vec![0; titanite::HEADER_MAX_LEN];
|
let mut input = vec![0; titanite::HEADER_MAX_LEN];
|
||||||
match stream.read(&mut input) {
|
match stream.read(&mut input) {
|
||||||
Ok(0) => println!("[{}] [warning] [{peer}] Peer closed connection", now()),
|
Ok(0) => println!("[{}] [warning] [{peer}] Peer closed connection", now()),
|
||||||
Ok(s) => match Request::from_bytes(&input[..s]) {
|
Ok(s) => match Request::from_bytes(&input[..s]) {
|
||||||
Ok(request) => match request {
|
Ok(request) => match request {
|
||||||
Request::Gemini(this) => gemini(this, argument, peer, stream),
|
Request::Gemini(this) => gemini(this, argument, peer, &mut stream),
|
||||||
Request::Titan(this) => titan(this, argument, peer, stream),
|
Request::Titan(this) => titan(this, argument, peer, &mut stream),
|
||||||
},
|
},
|
||||||
Err(e) => send(
|
Err(e) => send(
|
||||||
&response::failure::temporary::General {
|
&response::failure::temporary::General {
|
||||||
message: Some("Internal server error".to_string()),
|
message: Some("Internal server error".to_string()),
|
||||||
}
|
}
|
||||||
.into_bytes(),
|
.into_bytes(),
|
||||||
stream,
|
&mut stream,
|
||||||
|result| match result {
|
|result| match result {
|
||||||
Ok(()) => println!("[{}] [warning] [{peer}] {e}", now()),
|
Ok(()) => println!("[{}] [warning] [{peer}] {e}", now()),
|
||||||
Err(e) => println!("[{}] [error] [{peer}] {e}", now()),
|
Err(e) => println!("[{}] [error] [{peer}] {e}", now()),
|
||||||
|
|
@ -78,7 +85,7 @@ fn handle(argument: Arc<Argument>, peer: SocketAddr, stream: &mut TlsStream<TcpS
|
||||||
message: Some("Internal server error".to_string()),
|
message: Some("Internal server error".to_string()),
|
||||||
}
|
}
|
||||||
.into_bytes(),
|
.into_bytes(),
|
||||||
stream,
|
&mut stream,
|
||||||
|result| match result {
|
|result| match result {
|
||||||
Ok(()) => println!("[{}] [warning] [{peer}] {e}", now()),
|
Ok(()) => println!("[{}] [warning] [{peer}] {e}", now()),
|
||||||
Err(e) => println!("[{}] [error] [{peer}] {e}", now()),
|
Err(e) => println!("[{}] [error] [{peer}] {e}", now()),
|
||||||
|
|
@ -86,6 +93,9 @@ fn handle(argument: Arc<Argument>, peer: SocketAddr, stream: &mut TlsStream<TcpS
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Err(e) => println!("[{}] [warning] [{peer}] Handshake issue: {e}", now()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn gemini(
|
fn gemini(
|
||||||
gemini: titanite::request::Gemini,
|
gemini: titanite::request::Gemini,
|
||||||
|
|
@ -94,19 +104,34 @@ fn gemini(
|
||||||
stream: &mut TlsStream<TcpStream>,
|
stream: &mut TlsStream<TcpStream>,
|
||||||
) {
|
) {
|
||||||
use titanite::*;
|
use titanite::*;
|
||||||
|
println!("[{}] [info] [{peer}] Request: {}", now(), gemini.url);
|
||||||
match storage::Item::from_url(gemini.url.as_str(), &argument.directory) {
|
match storage::Item::from_url(gemini.url.as_str(), &argument.directory) {
|
||||||
Ok(item) => send(
|
Ok(item) => {
|
||||||
|
let mut read: usize = 0;
|
||||||
|
match stream.write_all(
|
||||||
&response::success::Default {
|
&response::success::Default {
|
||||||
mime: item.mime,
|
mime: item.mime,
|
||||||
//data: item.file.read(vec![1000]),
|
data: &[], // init empty
|
||||||
}
|
}
|
||||||
.into_bytes(),
|
.into_bytes(),
|
||||||
stream,
|
) {
|
||||||
|result| match result {
|
Ok(()) => loop {
|
||||||
Ok(()) => println!("[{}] [info] [{peer}] Request: {}", now(), gemini.url),
|
let mut data = vec![0; argument.chunk];
|
||||||
Err(e) => println!("[{}] [error] [{peer}] {e}", now()),
|
let l = item.file.read_at(&mut data, read as u64).unwrap();
|
||||||
|
stream.write_all(&data[..l]).unwrap();
|
||||||
|
read += l;
|
||||||
|
println!("[{}] [info] [{peer}] Chunk sent: {l} ({read} total)", now());
|
||||||
|
// EOF
|
||||||
|
if l == 0 {
|
||||||
|
stream.flush().unwrap();
|
||||||
|
stream.shutdown().unwrap();
|
||||||
|
println!("[{}] [info] [{peer}] Response: {read} bytes", now());
|
||||||
|
break;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
),
|
Err(e) => println!("[{}] [error] [{peer}] {e}", now()),
|
||||||
|
}
|
||||||
|
}
|
||||||
Err(e) => send(
|
Err(e) => send(
|
||||||
&response::failure::permanent::NotFound {
|
&response::failure::permanent::NotFound {
|
||||||
message: Some("Not found".to_string()),
|
message: Some("Not found".to_string()),
|
||||||
|
|
@ -184,7 +209,7 @@ fn titan(
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate client-side limits (from header)
|
// validate client-side limits (from header)
|
||||||
if titan.size > total {
|
if total > titan.size {
|
||||||
if let Err(e) = tmp.delete() {
|
if let Err(e) = tmp.delete() {
|
||||||
println!("[{}] [error] [{peer}] {e}", now());
|
println!("[{}] [error] [{peer}] {e}", now());
|
||||||
}
|
}
|
||||||
|
|
@ -227,7 +252,7 @@ fn titan(
|
||||||
}
|
}
|
||||||
|
|
||||||
// just to make sure
|
// just to make sure
|
||||||
if titan.size > total {
|
if total > titan.size {
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue