Rid ourselves of the old Network trait.
This commit is contained in:
@@ -3,9 +3,9 @@ use crate::messages::{
|
|||||||
AuthenticationMethod, ClientConnectionCommand, ClientConnectionRequest, ClientGreeting,
|
AuthenticationMethod, ClientConnectionCommand, ClientConnectionRequest, ClientGreeting,
|
||||||
ClientUsernamePassword, ServerAuthResponse, ServerChoice, ServerResponse, ServerResponseStatus,
|
ClientUsernamePassword, ServerAuthResponse, ServerChoice, ServerResponse, ServerResponseStatus,
|
||||||
};
|
};
|
||||||
use crate::network::{Network, SOCKSv5Address};
|
use crate::network::generic::Networklike;
|
||||||
use async_std::net::IpAddr;
|
|
||||||
use futures::io::{AsyncRead, AsyncWrite};
|
use futures::io::{AsyncRead, AsyncWrite};
|
||||||
|
use log::{warn, trace};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
@@ -27,14 +27,14 @@ pub enum SOCKSv5Error {
|
|||||||
pub struct SOCKSv5Client<S, N>
|
pub struct SOCKSv5Client<S, N>
|
||||||
where
|
where
|
||||||
S: AsyncRead + AsyncWrite,
|
S: AsyncRead + AsyncWrite,
|
||||||
N: Network,
|
N: Networklike,
|
||||||
{
|
{
|
||||||
_network: N,
|
_network: N,
|
||||||
stream: S,
|
stream: S,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LoginInfo {
|
pub struct LoginInfo {
|
||||||
username_password: Option<UsernamePassword>,
|
pub username_password: Option<UsernamePassword>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UsernamePassword {
|
pub struct UsernamePassword {
|
||||||
@@ -45,7 +45,7 @@ pub struct UsernamePassword {
|
|||||||
impl<S, N> SOCKSv5Client<S, N>
|
impl<S, N> SOCKSv5Client<S, N>
|
||||||
where
|
where
|
||||||
S: AsyncRead + AsyncWrite + Send + Unpin,
|
S: AsyncRead + AsyncWrite + Send + Unpin,
|
||||||
N: Network,
|
N: Networklike,
|
||||||
{
|
{
|
||||||
/// Create a new SOCKSv5 client connection over the given steam, using the given
|
/// Create a new SOCKSv5 client connection over the given steam, using the given
|
||||||
/// authentication information.
|
/// authentication information.
|
||||||
@@ -56,25 +56,35 @@ where
|
|||||||
acceptable_methods.push(AuthenticationMethod::UsernameAndPassword);
|
acceptable_methods.push(AuthenticationMethod::UsernameAndPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"Computed acceptable methods -- {:?} -- sending client greeting.",
|
||||||
|
acceptable_methods
|
||||||
|
);
|
||||||
let client_greeting = ClientGreeting { acceptable_methods };
|
let client_greeting = ClientGreeting { acceptable_methods };
|
||||||
|
|
||||||
client_greeting.write(&mut stream).await?;
|
client_greeting.write(&mut stream).await?;
|
||||||
let server_choice = ServerChoice::read(Pin::new(&mut stream)).await?;
|
trace!("Write client greeting, waiting for server's choice.");
|
||||||
|
let server_choice = ServerChoice::read(&mut stream).await?;
|
||||||
|
|
||||||
|
trace!("Received server's choice: {}", server_choice.chosen_method);
|
||||||
match server_choice.chosen_method {
|
match server_choice.chosen_method {
|
||||||
AuthenticationMethod::None => {}
|
AuthenticationMethod::None => {}
|
||||||
|
|
||||||
AuthenticationMethod::UsernameAndPassword => {
|
AuthenticationMethod::UsernameAndPassword => {
|
||||||
let (username, password) = if let Some(ref linfo) = login.username_password {
|
let (username, password) = if let Some(ref linfo) = login.username_password {
|
||||||
|
trace!("Server requested username/password, getting data from login info.");
|
||||||
(linfo.username.clone(), linfo.password.clone())
|
(linfo.username.clone(), linfo.password.clone())
|
||||||
} else {
|
} else {
|
||||||
|
warn!("Server requested username/password, but we weren't provided one.");
|
||||||
("".to_string(), "".to_string())
|
("".to_string(), "".to_string())
|
||||||
};
|
};
|
||||||
|
|
||||||
let auth_request = ClientUsernamePassword { username, password };
|
let auth_request = ClientUsernamePassword { username, password };
|
||||||
|
|
||||||
|
trace!("Writing password information.");
|
||||||
auth_request.write(&mut stream).await?;
|
auth_request.write(&mut stream).await?;
|
||||||
let server_response = ServerAuthResponse::read(Pin::new(&mut stream)).await?;
|
let server_response = ServerAuthResponse::read(&mut stream).await?;
|
||||||
|
trace!("Got server response: {}", server_response.success);
|
||||||
|
|
||||||
if !server_response.success {
|
if !server_response.success {
|
||||||
return Err(SOCKSv5Error::AuthenticationFailed);
|
return Err(SOCKSv5Error::AuthenticationFailed);
|
||||||
@@ -88,45 +98,7 @@ where
|
|||||||
x => return Err(SOCKSv5Error::UnsupportedAuthMethodChosen(x)),
|
x => return Err(SOCKSv5Error::UnsupportedAuthMethodChosen(x)),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trace!("Returning new SOCKSv5Client object!");
|
||||||
Ok(SOCKSv5Client { _network, stream })
|
Ok(SOCKSv5Client { _network, stream })
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn connect_internal(
|
|
||||||
&mut self,
|
|
||||||
addr: SOCKSv5Address,
|
|
||||||
port: u16,
|
|
||||||
) -> Result<N::Stream, SOCKSv5Error> {
|
|
||||||
let request = ClientConnectionRequest {
|
|
||||||
command_code: ClientConnectionCommand::EstablishTCPStream,
|
|
||||||
destination_address: addr,
|
|
||||||
destination_port: port,
|
|
||||||
};
|
|
||||||
|
|
||||||
request.write(&mut self.stream).await?;
|
|
||||||
let response = ServerResponse::read(Pin::new(&mut self.stream)).await?;
|
|
||||||
|
|
||||||
if response.status == ServerResponseStatus::RequestGranted {
|
|
||||||
unimplemented!()
|
|
||||||
} else {
|
|
||||||
Err(SOCKSv5Error::from(response.status))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn connect(&mut self, addr: IpAddr, port: u16) -> Result<N::Stream, SOCKSv5Error> {
|
|
||||||
assert!(port != 0);
|
|
||||||
match addr {
|
|
||||||
IpAddr::V4(a) => self.connect_internal(SOCKSv5Address::IP4(a), port).await,
|
|
||||||
IpAddr::V6(a) => self.connect_internal(SOCKSv5Address::IP6(a), port).await,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn connect_name(
|
|
||||||
&mut self,
|
|
||||||
name: String,
|
|
||||||
port: u16,
|
|
||||||
) -> Result<N::Stream, SOCKSv5Error> {
|
|
||||||
format!("hello {}", 'a');
|
|
||||||
self.connect_internal(SOCKSv5Address::Name(name), port)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,33 +12,3 @@ pub use crate::network::standard::Builtin;
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use futures::{AsyncRead, AsyncWrite};
|
use futures::{AsyncRead, AsyncWrite};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
pub trait Network {
|
|
||||||
type Stream: AsyncRead + AsyncWrite + Clone + Send + Sync + Unpin + 'static;
|
|
||||||
type Listener: SingleShotListener<Self::Stream, Self::Error> + Send + Sync + 'static;
|
|
||||||
type UdpSocket;
|
|
||||||
type Error: fmt::Debug + fmt::Display + Into<ServerResponseStatus>;
|
|
||||||
|
|
||||||
async fn connect<A: Into<SOCKSv5Address>>(
|
|
||||||
&mut self,
|
|
||||||
addr: A,
|
|
||||||
port: u16,
|
|
||||||
) -> Result<Self::Stream, Self::Error>;
|
|
||||||
async fn udp_socket<A: Into<SOCKSv5Address>>(
|
|
||||||
&mut self,
|
|
||||||
addr: A,
|
|
||||||
port: Option<u16>,
|
|
||||||
) -> Result<Self::UdpSocket, Self::Error>;
|
|
||||||
async fn listen<A: Into<SOCKSv5Address>>(
|
|
||||||
&mut self,
|
|
||||||
addr: A,
|
|
||||||
port: Option<u16>,
|
|
||||||
) -> Result<Self::Listener, Self::Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
pub trait SingleShotListener<Stream, Error> {
|
|
||||||
async fn accept(self) -> Result<Stream, Error>;
|
|
||||||
fn info(&self) -> Result<(SOCKSv5Address, u16), Error>;
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user