Skip to content

Commit 3fa806d

Browse files
authoredJan 6, 2025··
Restructure and add library target (#394)
* move config (clap) structs into config.rs - copied all config structs into config.rs, along with all `use` statements - made everything `pub` - changed main.rs to import these structs * remove unused imports and move parsing tests to config.rs * cargo fmt * separate library and cli - make root package a cargo workspace - move code to start client/server tunnels into lib.rs - move rest of main.rs into wstunnel-cli bin package - move "Wstunnel" config struct into bin package - the fields here are only applicable to the CLI * cargo fmt * move clap parsing into feature * move argument parsing functions under clap feature * update wstunnel-cli binary name and build workflow * cargo fmt, fix tests * update build instructions * only use required tokio features
1 parent 92ec4a9 commit 3fa806d

File tree

10 files changed

+1381
-1272
lines changed

10 files changed

+1381
-1272
lines changed
 

‎.github/workflows/release.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ jobs:
137137
with:
138138
command: build
139139
use-cross: ${{ !contains(matrix.platform.target, 'x86_64') || contains(matrix.platform.target, 'freebsd') }}
140-
args: ${{ matrix.platform.build-args }} --target ${{ matrix.platform.target }}
140+
args: ${{ matrix.platform.build-args }} --package wstunnel-cli --target ${{ matrix.platform.target }}
141141

142142
- name: Store artifact
143143
uses: actions/upload-artifact@v4

‎Cargo.lock

+13-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
[workspace]
2+
members = ["wstunnel-cli"]
3+
14
[package]
25
name = "wstunnel"
36
version = "10.1.8"
@@ -13,7 +16,7 @@ scopeguard = "1.2.0"
1316

1417
bb8 = { version = "0.9.0", features = [] }
1518
bytes = { version = "1.9.0", features = [] }
16-
clap = { version = "4.5.23", features = ["derive", "env"] }
19+
clap = { version = "4.5.23", features = ["derive", "env"], optional = true }
1720
fast-socks5 = { version = "0.10.0", features = [] }
1821
fastwebsockets = { git = "https://github.com/erebe/fastwebsockets.git", features = ["upgrade", "simd", "unstable-split"] }
1922
futures-util = { version = "0.3.31" }
@@ -22,8 +25,6 @@ ppp = { version = "2.2.0", features = [] }
2225
async-channel = { version = "2.3.1", features = [] }
2326
arc-swap = { version = "1.7.1", features = [] }
2427

25-
fdlimit = "0.3.0"
26-
2728
# For config file parsing
2829
regex = { version = "1.11.1", default-features = false, features = ["std", "perf"] }
2930
serde_regex = "1.1.0"
@@ -45,11 +46,10 @@ rustls-pemfile = { version = "2.2.0", features = [] }
4546
x509-parser = "0.16.0"
4647
serde = { version = "1.0.216", features = ["derive"] }
4748
socket2 = { version = "0.5.8", features = [] }
48-
tokio = { version = "1.42.0", features = ["full"] }
49+
tokio = { version = "1.42.0", features = ["io-std", "net", "signal", "sync", "time"] }
4950
tokio-stream = { version = "0.1.17", features = ["net"] }
5051

5152
tracing = { version = "0.1.41", features = ["log"] }
52-
tracing-subscriber = { version = "0.3.19", features = ["env-filter", "fmt", "local-time"] }
5353
url = "2.5.4"
5454
urlencoding = "2.1.3"
5555
uuid = { version = "1.11.0", features = ["v7", "serde"] }
@@ -80,6 +80,9 @@ derive_more = { version = "1.0.0", features = ["from"] }
8080
[target.'cfg(target_os = "macos")'.dev-dependencies]
8181
get_if_addrs = "0.5.3"
8282

83+
[features]
84+
# Implements clap::Subcommand on config::Client and config::Server
85+
clap = ["dep:clap"]
8386

8487
[profile.release]
8588
lto = "fat"

‎README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,6 @@ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
675675
and run those commands at the root of the project
676676

677677
```
678-
cargo build
678+
cargo build --package wstunnel-cli
679679
target/debug/wstunnel ...
680680
```

‎src/config.rs

+744
Large diffs are not rendered by default.

‎src/lib.rs

+494
Large diffs are not rendered by default.

‎src/main.rs

-1,263
This file was deleted.

‎src/tunnel/transport/types.rs

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub enum TransportScheme {
1212
}
1313

1414
impl TransportScheme {
15+
#[cfg(feature = "clap")] // this is only used inside a clap value parser
1516
pub const fn values() -> &'static [Self] {
1617
&[Self::Ws, Self::Wss, Self::Http, Self::Https]
1718
}

‎wstunnel-cli/Cargo.toml

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[package]
2+
name = "wstunnel-cli"
3+
version = "10.1.8"
4+
edition = "2021"
5+
6+
[dependencies]
7+
anyhow = "1.0.95"
8+
9+
clap = { version = "4.5.23", features = ["derive", "env"] }
10+
11+
fdlimit = "0.3.0"
12+
13+
tokio = { version = "1.42.0", features = ["full"] }
14+
15+
tracing = { version = "0.1.41", features = ["log"] }
16+
tracing-subscriber = { version = "0.3.19", features = ["env-filter", "fmt", "local-time"] }
17+
18+
wstunnel = { path = ".." , features = ["clap"] }
19+
20+
[[bin]]
21+
name = "wstunnel"
22+
path = "src/main.rs"

‎wstunnel-cli/src/main.rs

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
use clap::Parser;
2+
use std::io;
3+
use std::str::FromStr;
4+
use tracing::warn;
5+
use tracing_subscriber::filter::Directive;
6+
use tracing_subscriber::EnvFilter;
7+
use wstunnel::config::{Client, Server};
8+
use wstunnel::LocalProtocol;
9+
use wstunnel::{run_client, run_server};
10+
11+
/// Use Websocket or HTTP2 protocol to tunnel {TCP,UDP} traffic
12+
/// wsTunnelClient <---> wsTunnelServer <---> RemoteHost
13+
#[derive(clap::Parser, Debug)]
14+
#[command(author, version, about, verbatim_doc_comment, long_about = None)]
15+
pub struct Wstunnel {
16+
#[command(subcommand)]
17+
commands: Commands,
18+
19+
/// Disable color output in logs
20+
#[arg(long, global = true, verbatim_doc_comment, env = "NO_COLOR")]
21+
no_color: Option<String>,
22+
23+
/// *WARNING* The flag does nothing, you need to set the env variable *WARNING*
24+
/// Control the number of threads that will be used.
25+
/// By default, it is equal the number of cpus
26+
#[arg(
27+
long,
28+
global = true,
29+
value_name = "INT",
30+
verbatim_doc_comment,
31+
env = "TOKIO_WORKER_THREADS"
32+
)]
33+
nb_worker_threads: Option<u32>,
34+
35+
/// Control the log verbosity. i.e: TRACE, DEBUG, INFO, WARN, ERROR, OFF
36+
/// for more details: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#example-syntax
37+
#[arg(
38+
long,
39+
global = true,
40+
value_name = "LOG_LEVEL",
41+
verbatim_doc_comment,
42+
env = "RUST_LOG",
43+
default_value = "INFO"
44+
)]
45+
log_lvl: String,
46+
}
47+
48+
#[derive(clap::Subcommand, Debug)]
49+
pub enum Commands {
50+
Client(Box<Client>),
51+
Server(Box<Server>),
52+
}
53+
54+
#[tokio::main]
55+
async fn main() -> anyhow::Result<()> {
56+
let args = Wstunnel::parse();
57+
58+
// Setup logging
59+
let mut env_filter = EnvFilter::builder().parse(&args.log_lvl).expect("Invalid log level");
60+
if !(args.log_lvl.contains("h2::") || args.log_lvl.contains("h2=")) {
61+
env_filter = env_filter.add_directive(Directive::from_str("h2::codec=off").expect("Invalid log directive"));
62+
}
63+
let logger = tracing_subscriber::fmt()
64+
.with_ansi(args.no_color.is_none())
65+
.with_env_filter(env_filter);
66+
67+
// stdio tunnel capture stdio, so need to log into stderr
68+
if let Commands::Client(args) = &args.commands {
69+
if args
70+
.local_to_remote
71+
.iter()
72+
.filter(|x| matches!(x.local_protocol, LocalProtocol::Stdio { .. }))
73+
.count()
74+
> 0
75+
{
76+
logger.with_writer(io::stderr).init();
77+
} else {
78+
logger.init()
79+
}
80+
} else {
81+
logger.init();
82+
};
83+
if let Err(err) = fdlimit::raise_fd_limit() {
84+
warn!("Failed to set soft filelimit to hard file limit: {}", err)
85+
}
86+
87+
match args.commands {
88+
Commands::Client(args) => {
89+
run_client(*args).await?;
90+
}
91+
Commands::Server(args) => {
92+
run_server(*args).await?;
93+
}
94+
}
95+
96+
Ok(())
97+
}

0 commit comments

Comments
 (0)
Please sign in to comment.