initial commit

This commit is contained in:
DarkCat09 2024-10-18 18:40:04 +04:00
commit e80d4caec9
Signed by: DarkCat09
GPG key ID: BD3CE9B65916CD82
9 changed files with 845 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

431
Cargo.lock generated Normal file
View file

@ -0,0 +1,431 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
dependencies = [
"gimli",
]
[[package]]
name = "adler2"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
[[package]]
name = "async-trait"
version = "0.1.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "backtrace"
version = "0.3.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
dependencies = [
"addr2line",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
"windows-targets",
]
[[package]]
name = "bytes"
version = "1.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "gimli"
version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
[[package]]
name = "hashbrown"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
[[package]]
name = "hermit-abi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "indexmap"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
dependencies = [
"equivalent",
"hashbrown",
]
[[package]]
name = "libc"
version = "0.2.159"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "miniz_oxide"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
dependencies = [
"adler2",
]
[[package]]
name = "mio"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
dependencies = [
"hermit-abi",
"libc",
"wasi",
"windows-sys",
]
[[package]]
name = "object"
version = "0.36.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e"
dependencies = [
"memchr",
]
[[package]]
name = "pin-project-lite"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]]
name = "proc-macro2"
version = "1.0.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rustc-demangle"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "serde"
version = "1.0.210"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.210"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_spanned"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
dependencies = [
"serde",
]
[[package]]
name = "serde_test"
version = "1.0.177"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f901ee573cab6b3060453d2d5f0bae4e6d628c23c0a962ff9b5f1d7c8d4f1ed"
dependencies = [
"serde",
]
[[package]]
name = "smp-socks"
version = "0.1.0"
dependencies = [
"serde",
"serde_test",
"socks5-server",
"thiserror",
"tokio",
"toml",
]
[[package]]
name = "socket2"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "socks5-proto"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d91431c4672e25e372ef46bc554be8f315068c03608f99267a71ad32a12e8c4"
dependencies = [
"bytes",
"thiserror",
"tokio",
]
[[package]]
name = "socks5-server"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5223c26981806584cc38c74fddf58808dbdcf4724890471ced69e7a2e8d86345"
dependencies = [
"async-trait",
"bytes",
"socks5-proto",
"tokio",
]
[[package]]
name = "syn"
version = "2.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tokio"
version = "1.40.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998"
dependencies = [
"backtrace",
"bytes",
"libc",
"mio",
"pin-project-lite",
"socket2",
"tokio-macros",
"windows-sys",
]
[[package]]
name = "tokio-macros"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "toml"
version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit",
]
[[package]]
name = "toml_datetime"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.22.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
"winnow",
]
[[package]]
name = "unicode-ident"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winnow"
version = "0.6.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b"
dependencies = [
"memchr",
]

14
Cargo.toml Normal file
View file

@ -0,0 +1,14 @@
[package]
name = "smp-socks"
version = "0.1.0"
edition = "2021"
[dependencies]
serde = { version = "1.0.210", features = ["derive"] }
socks5-server = "0.10.1"
thiserror = "1.0.64"
tokio = { version = "1.40.0", features = ["macros", "rt-multi-thread", "io-util"] }
toml = { version = "0.8.19", default-features = false, features = ["parse"] }
[dev-dependencies]
serde_test = "1.0.177"

31
src/config.rs Normal file
View file

@ -0,0 +1,31 @@
use std::{collections::HashSet, io::Read, net::Ipv4Addr};
use crate::{error::AppResult, serde_addr::TargetAddr};
#[derive(serde::Deserialize)]
pub struct Config {
pub host: String,
pub port: u16,
pub local: HashSet<TargetAddr>,
pub remote: HashSet<TargetAddr>,
}
pub fn parse() -> AppResult<Config> {
if let Some(mut file) = std::env::var_os("CONFIG")
.and_then(|path| std::fs::File::open(path).ok())
.or_else(|| std::fs::File::open("config.toml").ok())
{
let mut buf = String::new();
file.read_to_string(&mut buf)?;
Ok(toml::from_str(&buf)?)
} else {
let mut local = HashSet::new();
local.insert((Ipv4Addr::new(127, 0, 0, 1).into(), 5232).into());
Ok(Config {
host: "0.0.0.0".to_owned(),
port: 5233,
local,
remote: HashSet::new(),
})
}
}

79
src/error.rs Normal file
View file

@ -0,0 +1,79 @@
use socks5_server::proto::Error as SocksProtoError;
use tokio::net::TcpStream;
pub type AppResult<T> = core::result::Result<T, AppError>;
#[derive(Debug)]
pub enum AppError {
IoError(std::io::Error),
InvalidConfig(toml::de::Error),
SocksError(SocksProtoError),
DataNotUtf8(std::string::FromUtf8Error),
ThirdPartyHost,
}
impl From<std::io::Error> for AppError {
#[inline]
fn from(value: std::io::Error) -> Self {
Self::IoError(value)
}
}
impl From<toml::de::Error> for AppError {
#[inline]
fn from(value: toml::de::Error) -> Self {
Self::InvalidConfig(value)
}
}
impl From<SocksProtoError> for AppError {
#[inline]
fn from(value: SocksProtoError) -> Self {
Self::SocksError(value)
}
}
impl From<std::string::FromUtf8Error> for AppError {
#[inline]
fn from(value: std::string::FromUtf8Error) -> Self {
Self::DataNotUtf8(value)
}
}
pub type HandlerResult<T> = core::result::Result<T, HandlerError>;
#[derive(Debug)]
pub struct HandlerError {
inner: AppError,
stream: TcpStream,
}
impl From<(AppError, TcpStream)> for HandlerError {
#[inline]
fn from(value: (AppError, TcpStream)) -> Self {
Self {
inner: value.0,
stream: value.1,
}
}
}
impl From<(SocksProtoError, TcpStream)> for HandlerError {
#[inline]
fn from(value: (SocksProtoError, TcpStream)) -> Self {
Self {
inner: AppError::SocksError(value.0),
stream: value.1,
}
}
}
impl From<(std::io::Error, TcpStream)> for HandlerError {
#[inline]
fn from(value: (std::io::Error, TcpStream)) -> Self {
Self {
inner: AppError::IoError(value.0),
stream: value.1,
}
}
}

58
src/handler.rs Normal file
View file

@ -0,0 +1,58 @@
use std::sync::Arc;
use crate::{
config::Config,
error::{AppError, HandlerError, HandlerResult},
};
use socks5_server::{
connection::state::NeedAuthenticate,
proto::{Address, Reply},
Command, IncomingConnection,
};
use tokio::net::TcpStream;
pub async fn handler(
conn: IncomingConnection<(), NeedAuthenticate>,
config: Arc<Config>,
) -> HandlerResult<()> {
let conn = conn.authenticate().await?.0;
match conn.wait().await? {
Command::Associate(cmd, _addr) => {
let _ = cmd
.reply(Reply::CommandNotSupported, Address::unspecified())
.await?
.close()
.await;
}
Command::Bind(cmd, _addr) => {
let _ = cmd
.reply(Reply::CommandNotSupported, Address::unspecified())
.await?
.close()
.await;
}
Command::Connect(cmd, addr) => {
let target = match addr {
Address::DomainAddress(host, port) => {
let Ok(host) = String::from_utf8(host) else {
let conn = cmd
.reply(Reply::GeneralFailure, Address::unspecified())
.await?
.into_inner();
return Err(
(std::io::Error::from(std::io::ErrorKind::InvalidData), conn).into(),
);
};
TcpStream::connect((host.as_ref(), port)).await
}
Address::SocketAddress(addr) => TcpStream::connect(addr).await,
};
}
}
Ok(())
}

9
src/host.rs Normal file
View file

@ -0,0 +1,9 @@
use std::{net::SocketAddr, sync::Arc};
use crate::{config::Config, error::AppResult};
pub fn parse_str(value: Vec<u8>, config: Arc<Config>) -> AppResult<SocketAddr> {
let host = String::from_utf8(value)?;
//
}

36
src/main.rs Normal file
View file

@ -0,0 +1,36 @@
mod config;
mod error;
mod handler;
// mod host;
mod serde_addr;
use std::sync::Arc;
use error::AppResult;
use handler::handler;
use socks5_server as socks;
use tokio::net::TcpListener;
#[tokio::main]
async fn main() -> AppResult<()> {
let config = Arc::new(config::parse()?);
let auth = Arc::new(socks::auth::NoAuth);
let listener = TcpListener::bind((config.host.as_str(), config.port)).await?;
let server = socks::Server::new(listener, auth);
while let Ok((conn, _addr)) = server.accept().await {
let config = config.clone();
tokio::spawn(async move {
match handler(conn, config).await {
Ok(()) => {}
Err(e) => {
//
}
}
});
}
Ok(())
}

186
src/serde_addr.rs Normal file
View file

@ -0,0 +1,186 @@
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs};
use serde::{de::Visitor, Deserialize};
pub const DEFAULT_PORT: u16 = 5232;
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum TargetAddr {
DomainName(String, u16),
IpAddress(SocketAddr),
}
impl<'de> Deserialize<'de> for TargetAddr {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_str(AddrVisitor)
}
}
impl ToSocketAddrs for TargetAddr {
type Iter = AddrIter;
fn to_socket_addrs(&self) -> std::io::Result<Self::Iter> {
Ok(match self {
Self::DomainName(host, port) => (host.as_str(), *port).to_socket_addrs()?.into(),
Self::IpAddress(sockaddr) => sockaddr.clone().into(),
})
}
}
impl From<(IpAddr, u16)> for TargetAddr {
#[inline]
fn from((addr, port): (IpAddr, u16)) -> Self {
Self::IpAddress(SocketAddr::new(addr, port))
}
}
pub struct AddrVisitor;
impl<'de> Visitor<'de> for AddrVisitor {
type Value = TargetAddr;
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
let v = v.trim();
let ipv6 = v.starts_with('[');
let mut port_idx = v.len();
let port = if ipv6 {
v.rfind("]:").and_then(|pos| {
port_idx = pos;
v.get(pos + 2..)
})
} else {
v.rfind(':').and_then(|pos| {
port_idx = pos;
v.get(pos + 1..)
})
}
.and_then(|port| {
port.parse::<u16>()
.map_err(|_| {
port_idx = v.len();
})
.ok()
})
.unwrap_or(DEFAULT_PORT);
let host = if ipv6 {
v.get(1..port_idx)
} else {
v.get(..port_idx)
}
.ok_or(serde::de::Error::missing_field("host"))?;
if ipv6 {
let addr = IpAddr::V6(host.parse().map_err(serde::de::Error::custom)?);
Ok((addr, port).into())
} else {
if let Ok(addr) = host.parse::<Ipv4Addr>() {
Ok((IpAddr::V4(addr), port).into())
} else if let Ok(addr) = host.parse::<Ipv6Addr>() {
Ok((IpAddr::V6(addr), port).into())
} else {
Ok(TargetAddr::DomainName(host.to_owned(), port))
}
}
}
fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
concat!(
"host:port ",
"where host is a domain or an ipv4/ipv6 addr, ",
"and optional port is u16",
),
)
}
}
pub enum AddrIter {
HostResolved(std::vec::IntoIter<SocketAddr>),
OneAddress(std::iter::Once<SocketAddr>),
}
impl Iterator for AddrIter {
type Item = SocketAddr;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match self {
Self::HostResolved(iter) => iter.next(),
Self::OneAddress(iter) => iter.next(),
}
}
}
impl From<std::vec::IntoIter<SocketAddr>> for AddrIter {
#[inline]
fn from(value: std::vec::IntoIter<SocketAddr>) -> Self {
Self::HostResolved(value)
}
}
impl From<SocketAddr> for AddrIter {
#[inline]
fn from(value: SocketAddr) -> Self {
Self::OneAddress(std::iter::once(value))
}
}
#[cfg(test)]
mod tests {
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use serde_test::{assert_de_tokens, Token};
use super::{TargetAddr, DEFAULT_PORT};
const LOCALHOST_V4: IpAddr = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
const TEST_V6: IpAddr = IpAddr::V6(Ipv6Addr::new(
0xfe80, 0x0, 0x0, 0x0, 0x721e, 0xd21f, 0x29a3, 0xf396,
));
#[test]
pub fn ipv4_without_port() {
let exp: TargetAddr = (LOCALHOST_V4, DEFAULT_PORT).into();
assert_de_tokens(&exp, &[Token::Str("127.0.0.1")]);
}
#[test]
pub fn ipv4_with_port() {
let exp: TargetAddr = (LOCALHOST_V4, 443).into();
assert_de_tokens(&exp, &[Token::Str("127.0.0.1:443")]);
}
#[test]
pub fn ipv6_without_port() {
let exp: TargetAddr = (TEST_V6, DEFAULT_PORT).into();
assert_de_tokens(&exp, &[Token::Str("fe80::721e:d21f:29a3:f396")]);
}
#[test]
pub fn ipv6_with_port() {
let exp: TargetAddr = (TEST_V6, 443).into();
assert_de_tokens(&exp, &[Token::Str("[fe80::721e:d21f:29a3:f396]:443")]);
}
#[test]
pub fn domain_without_port() {
let exp = TargetAddr::DomainName("smp.dc09.ru".to_owned(), DEFAULT_PORT);
assert_de_tokens(&exp, &[Token::Str("smp.dc09.ru")]);
}
#[test]
pub fn domain_with_port() {
let exp = TargetAddr::DomainName("xftp.dc09.ru".to_owned(), 443);
assert_de_tokens(&exp, &[Token::Str("xftp.dc09.ru:443")]);
}
}