use std::sync::Arc;
use std::time::Duration;
use rand::seq::SliceRandom;
use tokio::io::AsyncWriteExt;
use tokio::net::TcpStream;
use crate::ProxyResult;
use crate::proxy::Proxy;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProxyChain {
chain: Vec<Proxy>,
}
impl ProxyChain {
pub fn new() -> Self {
Self { chain: Vec::new() }
}
pub fn add_proxy(&mut self, proxy: impl Into<Proxy>) {
self.chain.push(proxy.into());
}
pub fn add_proxies(&mut self, proxies: Vec<impl Into<Proxy>>) {
let mut iter = Vec::new();
for proxy in proxies {
iter.push(proxy.into());
}
self.chain.extend(iter);
}
pub fn with_proxy(mut self, proxy: impl Into<Proxy>) -> Self {
self.chain.push(proxy.into());
self
}
pub fn with_proxies(mut self, proxies: Vec<impl Into<Proxy>>) -> Self {
let mut iter = Vec::new();
for proxy in proxies {
iter.push(proxy.into());
}
self.chain.extend(iter);
self
}
pub fn clear(&mut self) {
self.chain.clear();
}
pub fn proxies(&self) -> &Vec<Proxy> {
&self.chain
}
pub fn entrance_proxy(&self) -> Option<&Proxy> {
self.chain.first()
}
pub fn exit_proxy(&self) -> Option<&Proxy> {
self.chain.last()
}
pub fn node(&self) -> Vec<String> {
let mut node = Vec::new();
for proxy in &self.chain {
node.push(proxy.ip());
}
node
}
pub async fn connect(&mut self, target_host: impl Into<String>, target_port: u16, autoreorder: bool) -> ProxyResult<TcpStream> {
let trgt_host = target_host.into();
let trgt_port = target_port;
if autoreorder {
loop {
let chain_clone = self.chain.clone();
let first_proxy = &chain_clone[0];
let first_addr = first_proxy.addr();
let mut stream = match tokio::time::timeout(Duration::from_secs(15), TcpStream::connect(first_addr)).await {
Ok(r) => match r {
Ok(s) => s,
Err(_) => {
self.reorder();
continue;
}
},
Err(_) => {
self.reorder();
continue;
}
};
let mut chain_is_broken = false;
for proxy in &chain_clone[1..] {
let proxy_ip = proxy.ip();
let proxy_port = proxy.port();
match proxy.connect_with_stream(&mut stream, proxy_ip, proxy_port).await {
Ok(_) => {}
Err(_) => {
let _ = stream.shutdown().await;
self.reorder();
chain_is_broken = true;
break;
}
};
}
if chain_is_broken {
continue;
}
let last_proxy = &chain_clone[chain_clone.len() - 1];
match last_proxy.connect_with_stream(&mut stream, &trgt_host, trgt_port).await {
Ok(_) => {}
Err(_) => {
let _ = stream.shutdown().await;
self.reorder();
continue;
}
};
break Ok(stream);
}
} else {
let first_proxy = &self.chain[0];
let first_addr = first_proxy.addr();
let mut stream = TcpStream::connect(first_addr).await?;
for proxy in &self.chain[1..] {
let proxy_ip = proxy.ip();
let proxy_port = proxy.port();
proxy.connect_with_stream(&mut stream, proxy_ip, proxy_port).await?;
}
let last_proxy = &self.chain[self.chain.len() - 1];
last_proxy.connect_with_stream(&mut stream, &trgt_host, trgt_port).await?;
Ok(stream)
}
}
pub fn reorder(&mut self) {
let mut rng = rand::rng();
self.chain.shuffle(&mut rng);
}
}
impl From<Vec<String>> for ProxyChain {
fn from(value: Vec<String>) -> Self {
let mut chain = Vec::new();
for address in value {
chain.push(Proxy::from(address));
}
Self { chain }
}
}
impl From<Vec<&str>> for ProxyChain {
fn from(value: Vec<&str>) -> Self {
let mut chain = Vec::new();
for address in value {
chain.push(Proxy::from(address));
}
Self { chain }
}
}
impl From<&str> for ProxyChain {
fn from(value: &str) -> Self {
let pretty_value = value.replace(" ", "").replace("\n", "");
let chain: Vec<&str> = pretty_value.split(",").collect();
Self::from(chain)
}
}
impl From<String> for ProxyChain {
fn from(value: String) -> Self {
let pretty_value = value.replace(" ", "").replace("\n", "");
let chain: Vec<&str> = pretty_value.split(",").collect();
Self::from(chain)
}
}
impl From<Arc<ProxyChain>> for ProxyChain {
fn from(value: Arc<ProxyChain>) -> Self {
Self {
chain: value.chain.clone(),
}
}
}