aquatic_http: move request parsing into protocol crate

This commit is contained in:
Joakim Frostegård 2020-07-20 20:13:56 +02:00
parent 2521c89109
commit 95e25710dc
6 changed files with 43 additions and 30 deletions

2
Cargo.lock generated
View file

@ -79,7 +79,6 @@ dependencies = [
"either", "either",
"flume", "flume",
"hashbrown", "hashbrown",
"httparse",
"indexmap", "indexmap",
"itoa", "itoa",
"log", "log",
@ -123,6 +122,7 @@ dependencies = [
"criterion", "criterion",
"hashbrown", "hashbrown",
"hex", "hex",
"httparse",
"itoa", "itoa",
"log", "log",
"memchr", "memchr",

View file

@ -22,7 +22,6 @@ aquatic_http_protocol = { path = "../aquatic_http_protocol" }
either = "1" either = "1"
flume = "0.7" flume = "0.7"
hashbrown = { version = "0.7", features = ["serde"] } hashbrown = { version = "0.7", features = ["serde"] }
httparse = "1"
indexmap = "1" indexmap = "1"
itoa = "0.4" itoa = "0.4"
log = "0.4" log = "0.4"

View file

@ -9,7 +9,7 @@ use mio::net::TcpStream;
use native_tls::{TlsAcceptor, MidHandshakeTlsStream}; use native_tls::{TlsAcceptor, MidHandshakeTlsStream};
use aquatic_common_tcp::network::stream::Stream; use aquatic_common_tcp::network::stream::Stream;
use aquatic_http_protocol::request::Request; use aquatic_http_protocol::request::{Request, RequestParseError};
use crate::common::*; use crate::common::*;
@ -17,10 +17,9 @@ use crate::common::*;
#[derive(Debug)] #[derive(Debug)]
pub enum RequestReadError { pub enum RequestReadError {
NeedMoreData, NeedMoreData,
Invalid(anyhow::Error),
StreamEnded, StreamEnded,
Parse(anyhow::Error),
Io(::std::io::Error), Io(::std::io::Error),
Parse(::httparse::Error),
} }
@ -71,31 +70,20 @@ impl EstablishedConnection {
} }
} }
let mut headers = [httparse::EMPTY_HEADER; 16]; match Request::from_bytes(&self.buf[..self.bytes_read]){
let mut http_request = httparse::Request::new(&mut headers); Ok(request) => {
self.clear_buffer();
match http_request.parse(&self.buf[..self.bytes_read]){ Ok(request)
Ok(httparse::Status::Complete(_)) => {
if let Some(path) = http_request.path {
let res_request = Request::from_http_get_path(path);
self.clear_buffer();
res_request.map_err(RequestReadError::Invalid)
} else {
self.clear_buffer();
Err(RequestReadError::Invalid(anyhow::anyhow!("no http path")))
}
}, },
Ok(httparse::Status::Partial) => { Err(RequestParseError::NeedMoreData) => {
Err(RequestReadError::NeedMoreData) Err(RequestReadError::NeedMoreData)
}, },
Err(err) => { Err(RequestParseError::Invalid(err)) => {
self.clear_buffer(); self.clear_buffer();
Err(RequestReadError::Parse(err)) Err(RequestReadError::Parse(err))
} },
} }
} }

View file

@ -227,8 +227,8 @@ pub fn handle_connection_read_event(
// Stop reading data (defer to later events) // Stop reading data (defer to later events)
break; break;
}, },
Err(RequestReadError::Invalid(err)) => { Err(RequestReadError::Parse(err)) => {
info!("error reading request (invalid): {}", err); info!("error reading request (invalid): {:#?}", err);
let meta = ConnectionMeta { let meta = ConnectionMeta {
worker_index: socket_worker_index, worker_index: socket_worker_index,
@ -253,11 +253,6 @@ pub fn handle_connection_read_event(
break break
}, },
Err(RequestReadError::Parse(err)) => {
::log::info!("request httparse error: {}", err);
break
},
Err(RequestReadError::Io(err)) => { Err(RequestReadError::Io(err)) => {
::log::info!("error reading request (io): {}", err); ::log::info!("error reading request (io): {}", err);

View file

@ -23,6 +23,7 @@ anyhow = "1"
bendy = { version = "0.3", features = ["std", "serde"] } bendy = { version = "0.3", features = ["std", "serde"] }
hashbrown = { version = "0.7", features = ["serde"] } hashbrown = { version = "0.7", features = ["serde"] }
hex = { version = "0.4", default-features = false } hex = { version = "0.4", default-features = false }
httparse = "1"
itoa = "0.4" itoa = "0.4"
log = "0.4" log = "0.4"
memchr = "2" memchr = "2"

View file

@ -109,6 +109,12 @@ impl ScrapeRequest {
} }
pub enum RequestParseError {
NeedMoreData,
Invalid(anyhow::Error),
}
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum Request { pub enum Request {
Announce(AnnounceRequest), Announce(AnnounceRequest),
@ -117,6 +123,30 @@ pub enum Request {
impl Request { impl Request {
/// Parse Request from HTTP request bytes
pub fn from_bytes(bytes: &[u8]) -> Result<Self, RequestParseError> {
let mut headers = [httparse::EMPTY_HEADER; 16];
let mut http_request = httparse::Request::new(&mut headers);
match http_request.parse(bytes){
Ok(httparse::Status::Complete(_)) => {
if let Some(path) = http_request.path {
let res_request = Self::from_http_get_path(path);
res_request.map_err(RequestParseError::Invalid)
} else {
Err(RequestParseError::Invalid(anyhow::anyhow!("no http path")))
}
},
Ok(httparse::Status::Partial) => {
Err(RequestParseError::NeedMoreData)
},
Err(err) => {
Err(RequestParseError::Invalid(anyhow::anyhow!("httparse: {:?}", err)))
}
}
}
/// Parse Request from http path (GET `/announce?info_hash=...`) /// Parse Request from http path (GET `/announce?info_hash=...`)
/// ///
/// Existing serde-url decode crates were insufficient, so the decision was /// Existing serde-url decode crates were insufficient, so the decision was