mirror of
https://github.com/YGGverse/aquatic.git
synced 2026-03-31 17:55:36 +00:00
aquatic_udp: improve request parse errors, send less error responses
This commit is contained in:
parent
bfab6bb48f
commit
f0a15e9b6f
4 changed files with 78 additions and 67 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -216,6 +216,7 @@ name = "aquatic_udp_protocol"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
|
"either",
|
||||||
"quickcheck",
|
"quickcheck",
|
||||||
"quickcheck_macros",
|
"quickcheck_macros",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -216,21 +216,18 @@ fn read_requests(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
::log::debug!("request_from_bytes error: {:?}", err);
|
::log::debug!("Request::from_bytes error: {:?}", err);
|
||||||
|
|
||||||
if let Some(transaction_id) = err.transaction_id {
|
if let RequestParseError::Sendable {
|
||||||
let opt_message = if err.error.is_some() {
|
connection_id,
|
||||||
Some("Parse error".into())
|
transaction_id,
|
||||||
} else if let Some(message) = err.message {
|
err,
|
||||||
Some(message.into())
|
} = err
|
||||||
} else {
|
{
|
||||||
None
|
if connections.contains_key(&ConnectionKey::new(connection_id, src)) {
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(message) = opt_message {
|
|
||||||
let response = ErrorResponse {
|
let response = ErrorResponse {
|
||||||
transaction_id,
|
transaction_id,
|
||||||
message,
|
message: err.right_or("Parse error").into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
local_responses.push((response.into(), src));
|
local_responses.push((response.into(), src));
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ repository = "https://github.com/greatest-ape/aquatic"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
byteorder = "1"
|
byteorder = "1"
|
||||||
|
either = "1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
quickcheck = "1.0"
|
quickcheck = "1.0"
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ use std::io::{self, Cursor, Read, Write};
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
|
|
||||||
use byteorder::{NetworkEndian, ReadBytesExt, WriteBytesExt};
|
use byteorder::{NetworkEndian, ReadBytesExt, WriteBytesExt};
|
||||||
|
use either::Either;
|
||||||
|
|
||||||
use super::common::*;
|
use super::common::*;
|
||||||
|
|
||||||
|
|
@ -67,32 +68,40 @@ pub struct ScrapeRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RequestParseError {
|
pub enum RequestParseError {
|
||||||
pub transaction_id: Option<TransactionId>,
|
Sendable {
|
||||||
pub message: Option<String>,
|
connection_id: ConnectionId,
|
||||||
pub error: Option<io::Error>,
|
transaction_id: TransactionId,
|
||||||
|
err: Either<io::Error, &'static str>,
|
||||||
|
},
|
||||||
|
Unsendable {
|
||||||
|
err: Either<io::Error, &'static str>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RequestParseError {
|
impl RequestParseError {
|
||||||
pub fn new(err: io::Error, transaction_id: i32) -> Self {
|
pub fn sendable_io(err: io::Error, connection_id: i64, transaction_id: i32) -> Self {
|
||||||
Self {
|
Self::Sendable {
|
||||||
transaction_id: Some(TransactionId(transaction_id)),
|
connection_id: ConnectionId(connection_id),
|
||||||
message: None,
|
transaction_id: TransactionId(transaction_id),
|
||||||
error: Some(err),
|
err: Either::Left(err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn io(err: io::Error) -> Self {
|
pub fn sendable_text(text: &'static str, connection_id: i64, transaction_id: i32) -> Self {
|
||||||
Self {
|
Self::Sendable {
|
||||||
transaction_id: None,
|
connection_id: ConnectionId(connection_id),
|
||||||
message: None,
|
transaction_id: TransactionId(transaction_id),
|
||||||
error: Some(err),
|
err: Either::Right(text),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn text(transaction_id: i32, message: &str) -> Self {
|
pub fn unsendable_io(err: io::Error) -> Self {
|
||||||
Self {
|
Self::Unsendable {
|
||||||
transaction_id: Some(TransactionId(transaction_id)),
|
err: Either::Left(err),
|
||||||
message: Some(message.to_string()),
|
}
|
||||||
error: None,
|
}
|
||||||
|
pub fn unsendable_text(text: &'static str) -> Self {
|
||||||
|
Self::Unsendable {
|
||||||
|
err: Either::Right(text),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -171,13 +180,13 @@ impl Request {
|
||||||
|
|
||||||
let connection_id = cursor
|
let connection_id = cursor
|
||||||
.read_i64::<NetworkEndian>()
|
.read_i64::<NetworkEndian>()
|
||||||
.map_err(RequestParseError::io)?;
|
.map_err(RequestParseError::unsendable_io)?;
|
||||||
let action = cursor
|
let action = cursor
|
||||||
.read_i32::<NetworkEndian>()
|
.read_i32::<NetworkEndian>()
|
||||||
.map_err(RequestParseError::io)?;
|
.map_err(RequestParseError::unsendable_io)?;
|
||||||
let transaction_id = cursor
|
let transaction_id = cursor
|
||||||
.read_i32::<NetworkEndian>()
|
.read_i32::<NetworkEndian>()
|
||||||
.map_err(RequestParseError::io)?;
|
.map_err(RequestParseError::unsendable_io)?;
|
||||||
|
|
||||||
match action {
|
match action {
|
||||||
// Connect
|
// Connect
|
||||||
|
|
@ -188,8 +197,7 @@ impl Request {
|
||||||
})
|
})
|
||||||
.into())
|
.into())
|
||||||
} else {
|
} else {
|
||||||
Err(RequestParseError::text(
|
Err(RequestParseError::unsendable_text(
|
||||||
transaction_id,
|
|
||||||
"Protocol identifier missing",
|
"Protocol identifier missing",
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
@ -201,39 +209,39 @@ impl Request {
|
||||||
let mut peer_id = [0; 20];
|
let mut peer_id = [0; 20];
|
||||||
let mut ip = [0; 4];
|
let mut ip = [0; 4];
|
||||||
|
|
||||||
cursor
|
cursor.read_exact(&mut info_hash).map_err(|err| {
|
||||||
.read_exact(&mut info_hash)
|
RequestParseError::sendable_io(err, connection_id, transaction_id)
|
||||||
.map_err(|err| RequestParseError::new(err, transaction_id))?;
|
})?;
|
||||||
cursor
|
cursor.read_exact(&mut peer_id).map_err(|err| {
|
||||||
.read_exact(&mut peer_id)
|
RequestParseError::sendable_io(err, connection_id, transaction_id)
|
||||||
.map_err(|err| RequestParseError::new(err, transaction_id))?;
|
})?;
|
||||||
|
|
||||||
let bytes_downloaded = cursor
|
let bytes_downloaded = cursor.read_i64::<NetworkEndian>().map_err(|err| {
|
||||||
.read_i64::<NetworkEndian>()
|
RequestParseError::sendable_io(err, connection_id, transaction_id)
|
||||||
.map_err(|err| RequestParseError::new(err, transaction_id))?;
|
})?;
|
||||||
let bytes_left = cursor
|
let bytes_left = cursor.read_i64::<NetworkEndian>().map_err(|err| {
|
||||||
.read_i64::<NetworkEndian>()
|
RequestParseError::sendable_io(err, connection_id, transaction_id)
|
||||||
.map_err(|err| RequestParseError::new(err, transaction_id))?;
|
})?;
|
||||||
let bytes_uploaded = cursor
|
let bytes_uploaded = cursor.read_i64::<NetworkEndian>().map_err(|err| {
|
||||||
.read_i64::<NetworkEndian>()
|
RequestParseError::sendable_io(err, connection_id, transaction_id)
|
||||||
.map_err(|err| RequestParseError::new(err, transaction_id))?;
|
})?;
|
||||||
let event = cursor
|
let event = cursor.read_i32::<NetworkEndian>().map_err(|err| {
|
||||||
.read_i32::<NetworkEndian>()
|
RequestParseError::sendable_io(err, connection_id, transaction_id)
|
||||||
.map_err(|err| RequestParseError::new(err, transaction_id))?;
|
})?;
|
||||||
|
|
||||||
cursor
|
cursor.read_exact(&mut ip).map_err(|err| {
|
||||||
.read_exact(&mut ip)
|
RequestParseError::sendable_io(err, connection_id, transaction_id)
|
||||||
.map_err(|err| RequestParseError::new(err, transaction_id))?;
|
})?;
|
||||||
|
|
||||||
let key = cursor
|
let key = cursor.read_u32::<NetworkEndian>().map_err(|err| {
|
||||||
.read_u32::<NetworkEndian>()
|
RequestParseError::sendable_io(err, connection_id, transaction_id)
|
||||||
.map_err(|err| RequestParseError::new(err, transaction_id))?;
|
})?;
|
||||||
let peers_wanted = cursor
|
let peers_wanted = cursor.read_i32::<NetworkEndian>().map_err(|err| {
|
||||||
.read_i32::<NetworkEndian>()
|
RequestParseError::sendable_io(err, connection_id, transaction_id)
|
||||||
.map_err(|err| RequestParseError::new(err, transaction_id))?;
|
})?;
|
||||||
let port = cursor
|
let port = cursor.read_u16::<NetworkEndian>().map_err(|err| {
|
||||||
.read_u16::<NetworkEndian>()
|
RequestParseError::sendable_io(err, connection_id, transaction_id)
|
||||||
.map_err(|err| RequestParseError::new(err, transaction_id))?;
|
})?;
|
||||||
|
|
||||||
let opt_ip = if ip == [0; 4] {
|
let opt_ip = if ip == [0; 4] {
|
||||||
None
|
None
|
||||||
|
|
@ -277,7 +285,11 @@ impl Request {
|
||||||
.into())
|
.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => Err(RequestParseError::text(transaction_id, "Invalid action")),
|
_ => Err(RequestParseError::sendable_text(
|
||||||
|
"Invalid action",
|
||||||
|
connection_id,
|
||||||
|
transaction_id,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue