Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -319,12 +319,12 @@ jobs:
with:
use-flakehub: false

- name: Check with mobile
- name: Check with mobile lib
working-directory: ./lightway-client
run: nix develop -c cargo check --features=mobile
- name: Clippy with mobile
run: nix develop -c cargo check --lib --features=mobile-test
- name: Clippy with mobile lib
working-directory: ./lightway-client
run: nix develop -c cargo clippy --features=mobile --all-targets -- -D warnings
run: nix develop -c cargo clippy --lib --all-targets -- -D warnings
- name: Test with mobile features
working-directory: ./lightway-client
run: nix develop -c cargo test --features=mobile-test
Expand All @@ -342,7 +342,7 @@ jobs:
path: ${{ steps.build-android-aar.outputs.path }}
if-no-files-found: error
- name: Build JsonSchema
run: nix develop -c cargo run --features=mobile,wolfssl -p lightway-client -- -c client.schema.json -g jsonschema
run: nix develop -c cargo run --features=wolfssl -p lightway-client -- -c client.schema.json -g jsonschema
- name: Upload JsonSchema artifact
uses: actions/upload-artifact@v4.6.2
with:
Expand Down
2 changes: 1 addition & 1 deletion Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ run_task = { name = [ "build-android-uniffi-library", "bindgen-android", "bundle
description = "Build native libraries for all Android architectures (x86_64, x86, armeabi-v7a, arm64-v8a)"
condition = { env_set = [ "ANDROID_NDK_HOME" ] }
command = "cargo"
args = [ "ndk", "--bindgen", "-t", "x86_64", "-t", "x86", "-t", "armeabi-v7a", "-t", "arm64-v8a", "-o", "${ANDROID_UNIFFI_JNI_LIBS_DIR}", "build", "--features", "mobile", "--release", "-p", "lightway-client", "--lib" ]
args = [ "ndk", "--bindgen", "-t", "x86_64", "-t", "x86", "-t", "armeabi-v7a", "-t", "arm64-v8a", "-o", "${ANDROID_UNIFFI_JNI_LIBS_DIR}", "build", "--release", "-p", "lightway-client", "--lib" ]

[tasks.bindgen-android]
description = "Generate bindgen kotlin classes"
Expand Down
13 changes: 8 additions & 5 deletions lightway-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ crate-type = ["cdylib", "rlib"]

[features]
default = ["wolfssl"]
mobile = ["uniffi", "tracing-core", "tracing-panic"]
mobile-test = [ "mobile" ] # Only mock struct, no uniffi structs
mobile-test = ["dep:uniffi", "dep:tracing-core", "dep:tracing-panic"] # Only mock struct, no uniffi exports
boringssl = ["lightway-app-utils/boringssl"]
wolfssl = ["lightway-app-utils/wolfssl"]
debug = ["lightway-core/debug","lightway-app-utils/debug"]
Expand Down Expand Up @@ -54,10 +53,9 @@ tokio.workspace = true
tracing = { workspace = true, features = ["attributes"] }
tracing-subscriber = { workspace = true, features = ["env-filter"] }

# mobile feature
tracing-core = { version = "0.1.33", optional = true }
tracing-panic = { version = "0.1.2", optional = true }
uniffi = { workspace = true, optional = true }
tracing-core = { version = "0.1.33", optional =true }
tracing-panic = { version = "0.1.2", optional= true }

[dev-dependencies]
more-asserts.workspace = true
Expand All @@ -70,6 +68,11 @@ tempfile = "3.24.0"
tracing-test = "0.2.6"
tun-rs.workspace = true

[target.'cfg(any(target_os = "android", target_os = "ios", target_os = "tvos"))'.dependencies]
tracing-core = "0.1.33"
tracing-panic = "0.1.2"
uniffi = { workspace = true }

[target.'cfg(target_os = "android")'.dependencies]
tracing-android = "0.2.0"

Expand Down
26 changes: 14 additions & 12 deletions lightway-client/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,10 +345,10 @@ pub struct Config {
#[schemars(extend("x-cfg" = "windows"))]
pub enable_dpapi: bool,

/// SNI header for TLS connections
#[cfg(feature = "mobile")]
#[patch(attribute(clap(skip)))]
#[schemars(extend("x-cfg" = "mobile"))]
#[patch(attribute(clap(long)))]
#[patch(attribute(doc = r#"SNI header for TLS connections
Only used if `servers` is empty"#))]
/// ex: example.com
Comment thread
kp-antonio-yang marked this conversation as resolved.
pub sni_header: String,

#[patch(attribute(clap(short, long)))]
Expand Down Expand Up @@ -390,6 +390,8 @@ impl Config {
.then(|| std::mem::take(&mut self.server_dn)),
cipher: self.cipher,
outside_mtu: self.outside_mtu,
sni_header: (!self.sni_header.is_empty())
.then(|| std::mem::take(&mut self.sni_header)),
..Default::default()
}];
}
Expand Down Expand Up @@ -578,7 +580,6 @@ impl Default for Config {
wintun_ring_capacity: ByteSize::mib(8),
#[cfg(windows)]
enable_dpapi: false,
#[cfg(feature = "mobile")]
sni_header: String::new(),
accept_unknowns: false,
unknowns: HashMap::new(),
Expand Down Expand Up @@ -625,6 +626,10 @@ pub struct ConnectionConfig {
/// The CA Cert content or Path
#[serde(default)]
pub ca_cert: Option<String>,

/// SNI header for TLS connections
#[serde(default)]
pub sni_header: Option<String>,
}

impl ConnectionConfig {
Expand All @@ -634,7 +639,7 @@ impl ConnectionConfig {
}

/// Try build CA from ca_crt
#[cfg(feature = "mobile")]
#[cfg(any(mobile, feature = "mobile-test"))]
pub fn load_ca(&self) -> Result<lightway_core::tls::RootCertificate<'_>, Error> {
self.ca_cert
.as_ref()
Expand All @@ -651,7 +656,7 @@ impl ConnectionConfig {
}

/// Try build SocketAddress from server field
#[cfg(feature = "mobile")]
#[cfg(any(mobile, feature = "mobile-test"))]
pub fn skt_addr(&self) -> Result<std::net::SocketAddr, Error> {
self.server
.parse()
Expand All @@ -660,10 +665,7 @@ impl ConnectionConfig {
}

#[derive(Debug, thiserror::Error)]
#[cfg_attr(
all(feature = "mobile", not(feature = "mobile-test")),
derive(uniffi::Error)
)]
#[cfg_attr(all(mobile, not(feature = "mobile-test")), derive(uniffi::Error))]
pub enum Error {
/// Invalid network protocol
#[error("Invalid network protocol")]
Expand All @@ -674,7 +676,7 @@ pub enum Error {
#[error("Unable to load certificate")]
InvalidCertificate,

#[cfg(feature = "mobile")]
#[cfg(any(mobile, feature = "mobile-test"))]
/// Unable to parse the sokcet address
#[error("Invalid Socket Address")]
InvalidSocketAddress,
Expand Down
6 changes: 3 additions & 3 deletions lightway-client/src/io/outside/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ impl Tcp {
pub async fn new(
remote_addr: SocketAddr,
maybe_sock: Option<TcpStream>,
#[cfg(all(linux, not(feature = "mobile")))] fwmark: u32,
#[cfg(all(linux, not(feature = "mobile-test")))] fwmark: u32,
) -> Result<Self> {
let sock = match maybe_sock {
Some(s) => {
#[cfg(all(linux, not(feature = "mobile")))]
#[cfg(all(linux, not(feature = "mobile-test")))]
if fwmark != 0 {
let socket = socket2::SockRef::from(&s);
match socket.set_mark(fwmark) {
Expand All @@ -36,7 +36,7 @@ impl Tcp {
// SO_MARK must be set before connect() so that the SYN packet is also
// marked, ensuring all traffic (including connection setup) is subject
// to policy routing rules based on the mark.
#[cfg(all(linux, not(feature = "mobile")))]
#[cfg(all(linux, not(feature = "mobile-test")))]
if fwmark != 0 {
match socket2::SockRef::from(&socket).set_mark(fwmark) {
Ok(_) => tracing::info!("Applied firewall mark to outside TCP socket"),
Expand Down
4 changes: 2 additions & 2 deletions lightway-client/src/io/outside/udp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl Udp {
pub async fn new(
remote_addr: SocketAddr,
sock: Option<UdpSocket>,
#[cfg(all(linux, not(feature = "mobile")))] fwmark: u32,
#[cfg(all(linux, not(feature = "mobile-test")))] fwmark: u32,
) -> Result<Self> {
let peer_addr = tokio::net::lookup_host(remote_addr)
.await?
Expand All @@ -73,7 +73,7 @@ impl Udp {
// Apply the firewall mark *before* the socket is used for anything, so
// that no packet can escape unmarked and be captured by the tunnel's
// own routes.
#[cfg(all(linux, not(feature = "mobile")))]
#[cfg(all(linux, not(feature = "mobile-test")))]
if fwmark != 0 {
let socket = socket2::SockRef::from(&sock);
match socket.set_mark(fwmark) {
Expand Down
25 changes: 14 additions & 11 deletions lightway-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ pub mod platform;
#[cfg(desktop)]
pub mod route_manager;

#[cfg(feature = "mobile")]
#[cfg(any(mobile, feature = "mobile-test"))]
pub mod mobile;

#[cfg(all(feature = "mobile", not(feature = "mobile-test")))]
#[cfg(all(mobile, not(feature = "mobile-test")))]
uniffi::setup_scaffolding!();

use anyhow::{Context, Result, anyhow};
Expand Down Expand Up @@ -90,21 +90,18 @@ impl std::fmt::Debug for ClientConnectionMode {
}

#[derive(Debug)]
#[cfg_attr(
all(feature = "mobile", not(feature = "mobile-test")),
derive(uniffi::Enum)
)]
#[cfg_attr(all(mobile, not(feature = "mobile-test")), derive(uniffi::Enum))]
pub enum ClientResult {
UserDisconnect,
NetworkChange,

#[cfg(feature = "mobile")]
#[cfg(any(mobile, feature = "mobile-test"))]
ServerGoodbye,
}

#[derive(Debug, thiserror::Error)]
#[cfg_attr(
all(feature = "mobile", not(feature = "mobile-test")),
all(mobile, not(feature = "mobile-test")),
derive(uniffi::Error),
uniffi(flat_error)
)]
Expand All @@ -120,7 +117,7 @@ pub enum LightwayError {
#[error("Config Format Error: `{0}`")]
ConfigFormatError(#[from] serde_saphyr::Error),

#[cfg(feature = "mobile")]
#[cfg(any(mobile, feature = "mobile-test"))]
#[error("Logging bridge initialization error: `{0}`")]
LoggingBridgeError(#[from] crate::mobile::tracing_utils::LoggingBridgeError),
}
Expand Down Expand Up @@ -410,6 +407,9 @@ pub struct ClientConnectionConfig<EventHandler: 'static + Send + EventCallback>
#[educe(Debug(method(debug_pkt_codec_fac)))]
pub inside_pkt_codec: Option<PacketCodecFactoryType>,

/// SNI header for TLS connections
pub sni_header: Option<String>,

/// Allow injection of a custom handler for event callback
#[educe(Debug(ignore))]
pub event_handler: Option<EventHandler>,
Expand Down Expand Up @@ -445,6 +445,7 @@ impl<EventHandler: 'static + Send + EventCallback> ClientConnectionConfig<EventH
inside_plugins: Default::default(),
outside_plugins: Default::default(),
inside_pkt_codec: None,
sni_header: config.sni_header,
event_handler,
})
}
Expand Down Expand Up @@ -1140,6 +1141,7 @@ pub async fn connect<
inside_pkt_codec,
inside_plugins,
outside_plugins,
sni_header,
event_handler,
} = server_config;

Expand All @@ -1150,7 +1152,7 @@ pub async fn connect<
let mut sock = io::outside::Udp::new(
server,
maybe_sock,
#[cfg(all(linux, not(feature = "mobile")))]
#[cfg(all(linux, not(feature = "mobile-test")))]
config.fwmark,
)
.await
Expand Down Expand Up @@ -1184,7 +1186,7 @@ pub async fn connect<
let sock = io::outside::Tcp::new(
server,
maybe_sock,
#[cfg(all(linux, not(feature = "mobile")))]
#[cfg(all(linux, not(feature = "mobile-test")))]
config.fwmark,
)
.await
Expand Down Expand Up @@ -1278,6 +1280,7 @@ pub async fn connect<
.when_some(server_dn, |b, sdn| {
b.with_server_domain_name_validation(&sdn)
})
.when_some(sni_header.as_deref(), |b, sni| b.with_sni_header(sni))
.when(connection_type.is_datagram() && config.enable_pmtud, |b| {
b.with_pmtud_timer(pmtud_timer)
})
Expand Down
8 changes: 4 additions & 4 deletions lightway-client/src/mobile/lightway.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,6 @@ pub(crate) async fn async_lightway_start(
lightway_client_connect(LightwayClientConnectArgs {
instance_id,
connect_conf,
sni_header: config.sni_header.clone(),
socket: outside_sockets[instance_id].take(),
enable_keepalive: config.keepalive_continuous,
enable_expresslane: config.enable_expresslane,
Expand Down Expand Up @@ -553,7 +552,6 @@ struct LightwayConnection {
struct LightwayClientConnectArgs {
instance_id: usize,
connect_conf: ConnectionConfig,
sni_header: String,
socket: Option<OutsideSocket>,
enable_keepalive: bool,
enable_expresslane: bool,
Expand All @@ -568,7 +566,6 @@ async fn lightway_client_connect(
LightwayClientConnectArgs {
instance_id,
mut connect_conf,
sni_header,
socket,
enable_keepalive,
enable_expresslane,
Expand All @@ -590,6 +587,7 @@ async fn lightway_client_connect(
let auth = connect_conf.take_auth()?;
let server_sockaddr = connect_conf.skt_addr()?;
let server_dn = connect_conf.server_dn.take();
let sni_header = connect_conf.sni_header.take();

let (connection_type, outside_io): (ConnectionType, Arc<dyn OutsideIO>) = {
let builder = OutsideIOBuilder::new(socket, server_sockaddr);
Expand Down Expand Up @@ -644,7 +642,9 @@ async fn lightway_client_connect(
.when(server_dn.is_some(), |b| {
b.with_server_domain_name_validation(&server_dn.expect("checked in builder pattern"))
})
.when(!sni_header.is_empty(), |b| b.with_sni_header(&sni_header))
.when(sni_header.is_some(), |b| {
b.with_sni_header(&sni_header.expect("checked in builder pattern"))
})
.when(connection_type.is_datagram() && ENABLE_PMTUD, |b| {
b.with_pmtud_timer(pmtud_timer)
})
Expand Down
Loading