Skip to content
This repository was archived by the owner on Sep 20, 2024. It is now read-only.

Commit 03c28af

Browse files
committed
minor performance improvements
1 parent 881d7e4 commit 03c28af

File tree

7 files changed

+51
-61
lines changed

7 files changed

+51
-61
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "v2socks"
3-
version = "0.2.0"
3+
version = "0.2.1"
44
authors = ["ylxdzsw <[email protected]>"]
55
edition = "2018"
66

PKGBUILD

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
pkgname=v2socks
44
pkgdesc="An opinioned lightweight socks5 server and vmess (v2ray) client."
55
pkgrel=1
6-
pkgver=0.2.0
6+
pkgver=0.2.1
77
arch=(any)
88
url='https://github.com/ylxdzsw/v2socks'
99
license=(GPL3)

readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
V2socks
22
=======
33

4-
An opinioned lightweight socks5 server and vmess (v2ray) client implemented in Rust.
4+
An opinionated lightweight socks5 server and vmess (v2ray) client implemented in Rust.

src/lib.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
#![allow(irrefutable_let_patterns)]
12
#![allow(dead_code, unused_imports)]
2-
#![deny(bare_trait_objects)]
33
#![allow(non_camel_case_types)]
4+
#![deny(bare_trait_objects)]
5+
#![warn(clippy::all)]
46

57
mod socks;
68
mod vmess;
79

10+
use oh_my_rust::*;
811
pub use socks::*;
912
pub use vmess::*;
1013

@@ -18,9 +21,9 @@ pub enum Addr {
1821
impl std::fmt::Display for Addr {
1922
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2023
match self {
21-
Addr::V4(x) => std::fmt::Display::fmt(&std::net::Ipv4Addr::from(x.clone()), fmt),
22-
Addr::V6(x) => std::fmt::Display::fmt(&std::net::Ipv6Addr::from(x.clone()), fmt),
23-
Addr::Domain(x) => std::fmt::Display::fmt(&String::from_utf8(x.to_vec()).unwrap(), fmt) // somewhat ugly, need more time to fight the type checker
24+
Addr::V4(x) => std::fmt::Display::fmt(&std::net::Ipv4Addr::from(*x), fmt),
25+
Addr::V6(x) => std::fmt::Display::fmt(&std::net::Ipv6Addr::from(*x), fmt),
26+
Addr::Domain(x) => std::fmt::Display::fmt(std::str::from_utf8(x).msg(std::fmt::Error)?, fmt)
2427
}
2528
}
2629
}

src/main.rs

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,14 @@ fn main() {
2929
let server = Socks5Server::new(port);
3030
vmess(&server, proxy.into(), parse_uid(user_id).unwrap())
3131
},
32-
_ => {
33-
eprint!("{}", USAGE)
34-
},
32+
_ => eprint!("{}", USAGE)
3533
}
3634
}
3735

3836
fn parse_uid(x: &str) -> Option<[u8; 16]> {
39-
let mut r = [0; 16];
4037
let x = x.replace('-', "");
4138
let list: Vec<_> = (0..32).step_by(2).map(|i| u8::from_str_radix(&x[i..i+2], 16).unwrap()).collect();
42-
r.clone_from_slice(list.get(0..16)?);
43-
Some(r)
39+
list.get(0..16).map(|x| [0; 16].apply(|buf| buf.copy_from_slice(x)))
4440
}
4541

4642
fn is_normal_close(e: &std::io::Error) -> bool {
@@ -51,7 +47,7 @@ fn is_normal_close(e: &std::io::Error) -> bool {
5147
}
5248

5349
fn vmess(server: &Socks5Server, proxy: String, user_id: [u8; 16]) {
54-
let connect = Box::leak(Box::new(move |dest, port| {
50+
let connect = leak(move |dest, port| {
5551
let client = std::net::TcpStream::connect(&proxy)?;
5652
debug!("connect {}:{} through proxy", &dest, port);
5753

@@ -63,22 +59,19 @@ fn vmess(server: &Socks5Server, proxy: String, user_id: [u8; 16]) {
6359
let local_port = local.port();
6460

6561
Ok((local_addr, local_port, (dest, port, client)))
66-
}));
62+
});
6763

6864
#[allow(non_snake_case)]
69-
let pass = Box::leak(Box::new(move |(dest, port, conn): (Addr, u16, std::net::TcpStream), mut stream: std::net::TcpStream| {
70-
let mut key = [0; 16];
71-
thread_rng().fill_bytes(&mut key);
72-
73-
let mut IV = [0; 16];
74-
thread_rng().fill_bytes(&mut IV);
65+
let pass = leak(move |(dest, port, conn): (Addr, u16, std::net::TcpStream), mut stream: std::net::TcpStream| {
66+
let key = [0; 16].apply(|x| thread_rng().fill_bytes(x));
67+
let IV = [0; 16].apply(|x| thread_rng().fill_bytes(x));
7568

7669
{
7770
let conn = conn.try_clone().expect("failed to clone TCP handle");
7871
let mut stream = stream.try_clone().expect("failed to clone TCP handle");
7972

8073
std::thread::spawn(move || {
81-
let mut buffer = Box::new( unsafe { std::mem::uninitialized::<[u8; 16384]>() } );
74+
let mut buffer = Box::new([0; 16384]);
8275
let mut reader = match VmessReader::new(conn, key, IV) {
8376
Some(x) => x,
8477
None => return warn!("reader handshake failed")
@@ -88,21 +81,21 @@ fn vmess(server: &Socks5Server, proxy: String, user_id: [u8; 16]) {
8881
Ok(0) => break,
8982
Ok(x) => x,
9083
Err(ref e) if is_normal_close(e) => break,
91-
Err(e) => { error!("{}", e); break }
84+
Err(e) => { warn!("{}", e); break }
9285
};
9386

9487
match stream.write_all(&buffer[..len]) {
9588
Ok(_) => debug!("read {} bytes", len),
9689
Err(ref e) if is_normal_close(e) => break,
97-
Err(e) => { error!("{}", e); break }
90+
Err(e) => { warn!("{}", e); break }
9891
}
9992
}
10093
reader.close();
10194
debug!("closed reading")
10295
});
10396
}
10497

105-
let mut buffer = Box::new( unsafe { std::mem::uninitialized::<[u8; 16384]>() } );
98+
let mut buffer = Box::new([0; 16384]);
10699
let mut writer = match VmessWriter::new(conn, user_id, dest, port, key, IV) {
107100
Some(x) => x,
108101
None => return warn!("writer handshake failed")
@@ -112,19 +105,19 @@ fn vmess(server: &Socks5Server, proxy: String, user_id: [u8; 16]) {
112105
Ok(0) => break,
113106
Ok(x) => x,
114107
Err(ref e) if is_normal_close(e) => break,
115-
Err(e) => { error!("{}", e); break }
108+
Err(e) => { warn!("{}", e); break }
116109
};
117110

118111
match writer.write_all(&buffer[..len]) {
119112
Ok(_) => debug!("sent {} bytes", len),
120113
Err(ref e) if is_normal_close(e) => break,
121-
Err(e) => { error!("{}", e); break }
114+
Err(e) => { warn!("{}", e); break }
122115
}
123116
}
124117

125118
writer.close();
126119
debug!("closed writing");
127-
}));
120+
});
128121

129122
server.listen(connect, pass)
130123
}

src/socks.rs

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ macro_rules! close_on_error {
1515
match $ex {
1616
Ok(x) => x,
1717
Err(e) => {
18-
return error!("{}", e)
18+
return warn!("{}", e)
1919
}
2020
}
2121
}}
@@ -30,7 +30,7 @@ impl Socks5Server {
3030
Socks5Server { port }
3131
}
3232

33-
pub fn listen<T>(&self, connect: &'static (impl Fn(Addr, u16) -> std::io::Result<(Addr, u16, T)> + Sync), pass: &'static (impl Fn(T, TcpStream) + Sync)) {
33+
pub fn listen<T>(&self, connect: &'static (impl Fn(Addr, u16) -> std::io::Result<(Addr, u16, T)> + Sync), pass: &'static (impl Fn(T, TcpStream) + Sync)) -> ! {
3434
let socket = TcpListener::bind(format!("0.0.0.0:{}", self.port)).expect("Address already in use");
3535
info!("v2socks starts listening at 0.0.0.0:{}", self.port);
3636

@@ -44,32 +44,31 @@ impl Socks5Server {
4444
pass(proxy, stream);
4545
});
4646
}
47+
48+
unreachable!()
4749
}
4850
}
4951

5052
fn initialize(stream: &mut (impl ReadExt + Write)) -> Result<(), String> {
51-
let mut header = [0, 0];
52-
stream.read_exact(&mut header).map_err(|_| "read initial bits failed")?;
53-
53+
let header = read_exact!(stream, [0, 0]).msg("read initial bits failed")?;
54+
5455
if header[0] != 5 {
5556
return Err(format!("unsupported socks version {}", header[0]))
5657
}
5758

58-
let list: Vec<u8> = stream.read_exact_alloc(header[1] as usize).map_err(|_| "read methods failed")?;
59+
let list: Vec<u8> = stream.read_exact_alloc(header[1] as usize).msg("read methods failed")?;
5960

6061
if !list.contains(&0) {
61-
stream.write(&[5, 0xff]).map_err(|_| "write response failed")?;
62-
return Err("client do not support NO AUTH method".to_owned())
62+
stream.write(&[5, 0xff]).msg("write response failed")?;
63+
return Err("client do not support NO AUTH method".to_string())
6364
}
6465

65-
stream.write(&[5, 0]).map_err(|_| "write response failed")?;
66+
stream.write(&[5, 0]).msg("write response failed")?;
6667
Ok(())
6768
}
6869

6970
fn read_request(stream: &mut (impl ReadExt + Write)) -> Result<(Addr, u16), String> {
70-
let mut header = [0; 4];
71-
stream.read_exact(&mut header).map_err(|_| "read request header failed")?;
72-
let [ver, cmd, _rev, atyp] = header;
71+
let [ver, cmd, _rev, atyp] = read_exact!(stream, [0; 4]).msg("read request header failed")?;
7372

7473
if ver != 5 {
7574
return Err(format!("unsupported socks version {}", ver))
@@ -80,27 +79,24 @@ fn read_request(stream: &mut (impl ReadExt + Write)) -> Result<(Addr, u16), Stri
8079
}
8180

8281
let addr = match atyp {
83-
0x01 => Addr::V4(read_exact!(stream, [0; 4]).map_err(|_| "read v4 address failed")?),
84-
0x04 => Addr::V6(read_exact!(stream, [0; 16]).map_err(|_| "read v6 address failed")?),
82+
0x01 => Addr::V4(read_exact!(stream, [0; 4]).msg("read v4 address failed")?),
83+
0x04 => Addr::V6(read_exact!(stream, [0; 16]).msg("read v6 address failed")?),
8584
0x03 => {
86-
let mut len = [0];
87-
stream.read_exact(&mut len).map_err(|_| "read domain length failed")?;
88-
let len = len[0];
89-
90-
Addr::Domain(stream.read_exact_alloc(len as usize).map_err(|_| "read domain failed")?.into_boxed_slice())
85+
let len = read_exact!(stream, [0]).msg("read domain length failed")?[0];
86+
Addr::Domain(stream.read_exact_alloc(len as usize).msg("read domain failed")?.into_boxed_slice())
9187
},
92-
_ => return Err("unknown ATYP".to_owned())
88+
_ => return Err("unknown ATYP".to_string())
9389
};
9490

95-
let mut port: [u8; 2] = [0; 2];
96-
stream.read_exact(&mut port).map_err(|_| "read port failed")?;
97-
let port: u16 = (port[0] as u16) << 8 | port[1] as u16;
91+
let port = read_exact!(stream, [0; 2]).msg("read port failed")?;
92+
let port = (port[0] as u16) << 8 | port[1] as u16;
9893

9994
Ok((addr, port))
10095
}
10196

10297
fn reply_request(stream: &mut (impl ReadExt + Write), addr: Addr, port: u16) -> Result<(), String> {
103-
let mut reply = vec![5, 0, 0];
98+
let mut reply = Vec::with_capacity(22); // cover V4 and V6
99+
reply.extend_from_slice(&[5, 0, 0]);
104100

105101
match addr {
106102
Addr::V4(x) => {
@@ -121,7 +117,7 @@ fn reply_request(stream: &mut (impl ReadExt + Write), addr: Addr, port: u16) ->
121117
reply.push((port >> 8) as u8);
122118
reply.push(port as u8);
123119

124-
stream.write(&reply).map_err(|_| "write reply failed")?;
120+
stream.write(&reply).msg("write reply failed")?;
125121

126122
Ok(())
127123
}

src/vmess.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ impl<R: ReadExt> Read for VmessReader<R> {
8383
// 4. verify checksum
8484
let checksum = fnv1a(&buf[..len-4]);
8585
if checksum.to_be_bytes() != temp {
86-
panic!("fuck")
86+
return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid checksum!"))
8787
}
8888

8989
Ok(len-4)
@@ -182,8 +182,7 @@ impl<W: Write> VmessWriter<W> {
182182

183183
AES128CFB::new(header_key, header_IV).encode(&mut buffer);
184184

185-
self.writer.write_all(&buffer)?;
186-
Ok(())
185+
self.writer.write_all(&buffer)
187186
}
188187
}
189188

@@ -195,7 +194,7 @@ impl<W: Write> Write for VmessWriter<W> {
195194
buf.extend_from_slice(&fnv1a(data).to_be_bytes());
196195
buf.extend_from_slice(data);
197196
self.encoder.encode(&mut buf); // this is the right code. the fucking protocol document is misleading!
198-
self.writer.write_all(&mut buf)?;
197+
self.writer.write_all(&buf)?;
199198
Ok(data.len())
200199
}
201200

@@ -204,6 +203,7 @@ impl<W: Write> Write for VmessWriter<W> {
204203
}
205204
}
206205

206+
#[allow(clippy::unreadable_literal)]
207207
fn fnv1a(x: &[u8]) -> u32 {
208208
let prime = 16777619;
209209
let mut hash = 0x811c9dc5;
@@ -230,8 +230,7 @@ impl AES128CFB {
230230
fn encode(&mut self, data: &mut [u8]) {
231231
for byte in data.iter_mut() {
232232
if self.p == 16 {
233-
let temp = self.state.clone();
234-
crypto::aessafe::AesSafe128Encryptor::new(&self.key).encrypt_block(&temp, &mut self.state);
233+
crypto::aessafe::AesSafe128Encryptor::new(&self.key).encrypt_block(&self.state.clone(), &mut self.state);
235234
self.p = 0;
236235
}
237236
*byte ^= self.state[self.p];
@@ -243,8 +242,7 @@ impl AES128CFB {
243242
fn decode(&mut self, data: &mut [u8]) {
244243
for byte in data.iter_mut() {
245244
if self.p == 16 {
246-
let temp = self.state.clone();
247-
crypto::aessafe::AesSafe128Encryptor::new(&self.key).encrypt_block(&temp, &mut self.state); // yes it's encrypt
245+
crypto::aessafe::AesSafe128Encryptor::new(&self.key).encrypt_block(&self.state.clone(), &mut self.state); // yes it's encrypt
248246
self.p = 0;
249247
}
250248
let temp = *byte;

0 commit comments

Comments
 (0)