Add a separate trait for converting errors into server responses.
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
use crate::errors::{DeserializationError, SerializationError};
|
use crate::errors::{DeserializationError, SerializationError};
|
||||||
|
use crate::network::generic::IntoErrorResponse;
|
||||||
use crate::network::SOCKSv5Address;
|
use crate::network::SOCKSv5Address;
|
||||||
use crate::serialize::read_amt;
|
use crate::serialize::read_amt;
|
||||||
use crate::standard_roundtrip;
|
use crate::standard_roundtrip;
|
||||||
@@ -37,6 +38,12 @@ pub enum ServerResponseStatus {
|
|||||||
AddressTypeNotSupported,
|
AddressTypeNotSupported,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IntoErrorResponse for ServerResponseStatus {
|
||||||
|
fn into_response(&self) -> ServerResponseStatus {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct ServerResponse {
|
pub struct ServerResponse {
|
||||||
pub status: ServerResponseStatus,
|
pub status: ServerResponseStatus,
|
||||||
@@ -45,9 +52,9 @@ pub struct ServerResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ServerResponse {
|
impl ServerResponse {
|
||||||
pub fn error<E: Into<ServerResponseStatus>>(resp: E) -> ServerResponse {
|
pub fn error<E: IntoErrorResponse>(resp: &E) -> ServerResponse {
|
||||||
ServerResponse {
|
ServerResponse {
|
||||||
status: resp.into(),
|
status: resp.into_response(),
|
||||||
bound_address: SOCKSv5Address::IP4(Ipv4Addr::new(0, 0, 0, 0)),
|
bound_address: SOCKSv5Address::IP4(Ipv4Addr::new(0, 0, 0, 0)),
|
||||||
bound_port: 0,
|
bound_port: 0,
|
||||||
}
|
}
|
||||||
@@ -189,7 +196,7 @@ fn check_bad_command() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn short_write_fails_right() {
|
fn short_write_fails_right() {
|
||||||
let mut buffer = [0u8; 2];
|
let mut buffer = [0u8; 2];
|
||||||
let cmd = ServerResponse::error(ServerResponseStatus::AddressTypeNotSupported);
|
let cmd = ServerResponse::error(&ServerResponseStatus::AddressTypeNotSupported);
|
||||||
let mut cursor = Cursor::new(&mut buffer as &mut [u8]);
|
let mut cursor = Cursor::new(&mut buffer as &mut [u8]);
|
||||||
let result = task::block_on(cmd.write(&mut cursor));
|
let result = task::block_on(cmd.write(&mut cursor));
|
||||||
match result {
|
match result {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use crate::network::datagram::GenericDatagramSocket;
|
|||||||
use crate::network::listener::GenericListener;
|
use crate::network::listener::GenericListener;
|
||||||
use crate::network::stream::GenericStream;
|
use crate::network::stream::GenericStream;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use std::fmt::Display;
|
use std::fmt::{Debug, Display};
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait Networklike {
|
pub trait Networklike {
|
||||||
@@ -12,7 +12,7 @@ pub trait Networklike {
|
|||||||
/// for using only one; if you have a use case for separating your errors,
|
/// for using only one; if you have a use case for separating your errors,
|
||||||
/// please shoot the author(s) and email to split this into multiple types, one
|
/// please shoot the author(s) and email to split this into multiple types, one
|
||||||
/// for each trait function.
|
/// for each trait function.
|
||||||
type Error: Display + Into<ServerResponseStatus> + Send;
|
type Error: Debug + Display + IntoErrorResponse + Send;
|
||||||
|
|
||||||
/// Connect to the given address and port, over this kind of network. The
|
/// Connect to the given address and port, over this kind of network. The
|
||||||
/// underlying stream should behave somewhat like a TCP stream ... which
|
/// underlying stream should behave somewhat like a TCP stream ... which
|
||||||
@@ -46,3 +46,16 @@ pub trait Networklike {
|
|||||||
port: u16,
|
port: u16,
|
||||||
) -> Result<GenericDatagramSocket<Self::Error>, Self::Error>;
|
) -> Result<GenericDatagramSocket<Self::Error>, Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This trait is a hack; sorry about that. The thing is, we want to be able to
|
||||||
|
/// convert Errors from the `Networklike` trait into a `ServerResponseStatus`,
|
||||||
|
/// but want to do so on references to the error object rather than the actual
|
||||||
|
/// object. This is for the paired reason that (a) we want to be able to use
|
||||||
|
/// the errors in multiple places -- for example, to return a value to the client
|
||||||
|
/// and then also to whoever called the function -- and (b) some common errors
|
||||||
|
/// (I'm looking at you, `io::Error`) aren't `Clone`. So ... hence this overly-
|
||||||
|
/// specific trait.
|
||||||
|
pub trait IntoErrorResponse {
|
||||||
|
#[allow(clippy::wrong_self_convention)]
|
||||||
|
fn into_response(&self) -> ServerResponseStatus;
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ use async_trait::async_trait;
|
|||||||
use futures::AsyncWriteExt;
|
use futures::AsyncWriteExt;
|
||||||
use log::error;
|
use log::error;
|
||||||
|
|
||||||
|
use super::generic::IntoErrorResponse;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Builtin {}
|
pub struct Builtin {}
|
||||||
|
|
||||||
impl Builtin {
|
impl Builtin {
|
||||||
@@ -226,9 +229,9 @@ fn check_sanity() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<io::Error> for ServerResponseStatus {
|
impl IntoErrorResponse for io::Error {
|
||||||
fn from(e: io::Error) -> ServerResponseStatus {
|
fn into_response(&self) -> ServerResponseStatus {
|
||||||
match e.kind() {
|
match self.kind() {
|
||||||
io::ErrorKind::ConnectionRefused => ServerResponseStatus::ConnectionRefused,
|
io::ErrorKind::ConnectionRefused => ServerResponseStatus::ConnectionRefused,
|
||||||
io::ErrorKind::NotFound => ServerResponseStatus::HostUnreachable,
|
io::ErrorKind::NotFound => ServerResponseStatus::HostUnreachable,
|
||||||
_ => ServerResponseStatus::GeneralFailure,
|
_ => ServerResponseStatus::GeneralFailure,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use crate::network::address::{HasLocalAddress, SOCKSv5Address};
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use crate::network::datagram::Datagramlike;
|
use crate::network::datagram::Datagramlike;
|
||||||
use crate::network::datagram::GenericDatagramSocket;
|
use crate::network::datagram::GenericDatagramSocket;
|
||||||
use crate::network::generic::Networklike;
|
use crate::network::generic::{IntoErrorResponse, Networklike};
|
||||||
use crate::network::listener::{GenericListener, Listenerlike};
|
use crate::network::listener::{GenericListener, Listenerlike};
|
||||||
use crate::network::stream::GenericStream;
|
use crate::network::stream::GenericStream;
|
||||||
use crate::network::testing::datagram::TestDatagram;
|
use crate::network::testing::datagram::TestDatagram;
|
||||||
@@ -82,8 +82,8 @@ impl fmt::Display for TestStackError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<TestStackError> for ServerResponseStatus {
|
impl IntoErrorResponse for TestStackError {
|
||||||
fn from(_: TestStackError) -> Self {
|
fn into_response(&self) -> ServerResponseStatus {
|
||||||
ServerResponseStatus::GeneralFailure
|
ServerResponseStatus::GeneralFailure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user