Add focused tests for Instance nic context creation without creating a
real tun device.
Verify empty dev_name keeps the dedicated backend, while matching
shared dev_name values reuse the same shared virtual nic and get fresh
member ids on each recreation.
Route normal, DHCP, and mobile nic creation through one helper that
selects the shared backend when dev_name is configured.
Keep dedicated nic creation as the default for configs without a
dev_name, and keep no_tun handling in the existing callers.
Store a process-wide shared virtual nic registry behind each instance
so networks with the same dev_name attach to the same shared device.
Create the shared virtual nic dispatcher from the mobile tun fd.
Later shared members attach through their ring tunnel and do not
consume another fd. Dedicated mobile nic creation stays unchanged.
Fix mobile no-magic-dns cfg so the mobile tun path checks without
enabling magic-dns.
Route shared nic IP and route configuration through member claims.
Repeated addresses or routes now touch the OS device only when the
first owner appears, and are removed only after the last owner leaves.
Forward NicBackend shared operations to the member claim layer.
Dynamic proxy and public IPv6 route updates now go through NicBackend,
so they use the same ownership merge behavior.
Clean member claims when shared member registration is dropped. Keep
raw ifcfg access for non-Linux platform cleanup only, and document
that this raw path does not carry the netns guard.
Replace full flow table clears with a small FIFO order queue so overflow evicts only older flow ownership hints.
Keep lookup read-only on the packet hot path and prune stale queue entries when a shared member unregisters.
Parse shared virtual nic flow keys directly from IP payload bytes instead of building pnet packet wrappers on the dispatcher hot path.
Use a local HashMap for flow owner lookup and clear the bounded table on overflow instead of removing a BTreeMap entry by key order.
Move shared member and flow ownership state into the dispatcher task.
Use control messages for member register and unregister events.
Keep the member table lock off the packet forwarding path.
Add the shared NIC dispatcher that owns the underlying VirtualNic tunnel.
Connect member ring tunnels through a private member table.
Track reverse flow ownership from packets written by a member.
Replies read from the shared device go back to the same member.
Packets without an owner fall back to any active member.
Mark the shared NIC invalid when the underlying tunnel closes or fails.
Notify members so their NicCtx can rebuild.
Use create_ring_tunnel_pair for member-level shared NIC tunnels.
That replaces the custom packet stream and sink implementation.
Keep one side of each ring tunnel in SharedVirtualNic's member map.
Later dispatcher code can connect those endpoints to the shared device.
Add a shared NicCtx constructor that obtains a SharedVirtualNicMember from the registry and wraps it in NicBackend::Shared.
Keep NicCtx::new on the dedicated backend path so existing runtime behavior does not change before the shared tunnel implementation is ready.
Replace NicCtx's direct VirtualNic field with NicBackend while keeping the constructor on the dedicated backend path.
Move existing device creation, ifcfg lookup, IP assignment, and public IPv6 updater calls through backend helpers so shared mode can be wired in a later commit without changing the dedicated flow.
Introduce SharedVirtualNicMember as the per-instance handle for a shared virtual NIC and add a registry helper to create members.
Add NicBackend so NicCtx can later choose between dedicated VirtualNic and shared member-backed tunnel creation without changing the existing dedicated path.
Add a small registry keyed by dev_name so shared-mode setup can reuse one SharedVirtualNic per device name.
Track invalid shared NICs through a shared flag and replace them on the next get_or_create call.
Move TUN-specific configuration into VirtualNicConfig so VirtualNic and SharedVirtualNic no longer depend on ArcGlobalCtx.
Keep global context side effects in NicCtx, including the Windows generated device-name writeback.
Remove quinn-plaintext to fix connection errors caused
by different hash values across platforms.
On x64, maintain compatibility with quinn-plaintext.
* feat(ffi): add async data plane API
* feat(ffi): add async data plane examples
* test(ffi): make async Go dataplane tests self-contained
* docs(ffi): document Go async dataplane API
* docs(android): document dataplane JNI API
pnpm v11 introduces breaking changes that cause frozen installations
to fail:
1. The "pnpm" field in package.json is no longer read. Moved
`overrides` to `pnpm-workspace.yaml` to fix
`ERR_PNPM_LOCKFILE_CONFIG_MISMATCH`.
2. `strictDepBuilds` is now enabled by default. Added required
dependencies (esbuild, unrs-resolver, vue-demi) to `allowBuilds` in
the workspace config to fix `ERR_PNPM_IGNORED_BUILDS`.
Add config server client support for the C FFI and Android JNI bindings.
Reuse the existing easytier::web_client::run_web_client path and
NetworkInstanceManager; OHOS is unchanged.
Report successful remote config apply/delete operations through a
callback, with one JSON event per affected instance.
Keep the config server client and FFI data plane mutually exclusive: once
either side is in use, the other side returns an error instead of sharing
lifecycle state.
Use pbjson to support string deserialization for enum fields
This allows TOML configs like:
chainType = "Inbound"
instead of:
chainType = 1
- Maintain backward compatibility with integer values
- Default serialization format is now string
TomlConfigLoader::new_from_str() always calls NetworkIdentity::new()
with unwrap_or_default() on network_secret, converting None to ''.
This creates a non-zero SHA256 digest, causing credential nodes loaded
from TOML to be misidentified as regular nodes (with network_secret),
which breaks Noise handshake authentication.
Fix: check if secure_mode is enabled AND network_secret is absent/empty,
and call NetworkIdentity::new_credential() in that case.
The same detection already exists in:
- core.rs (CLI path, via --credential flag)
- launcher.rs (GUI/web path, via gen_config)
This makes TOML config loading consistent with the other two entry points.
1. Overview
This PR adds data plane APIs to easytier-ffi:
TCP Outbound:
- data_plane_tcp_connect
- data_plane_tcp_read
- data_plane_tcp_write
- data_plane_tcp_close
TCP Listener:
- data_plane_tcp_bind
- data_plane_tcp_accept
- data_plane_tcp_listener_close
UDP:
- data_plane_udp_bind
- data_plane_udp_send_to
- data_plane_udp_recv_from
- data_plane_udp_close
2. Key Changes
The main changes are focused on:
- easytier-contrib/easytier-ffi/src/lib.rs: Added FFI interfaces;
made ERROR_MSG thread-safe.
- easytier/src/gateway/socks5.rs: Bridges the data plane to the
existing Socks5 server logic.
- Added EasyTierUdpSocket, mainly wrapping ref-counting and
critical object (e.g., Socks5EntrySet) hold & drop logic,
and exposing common fields (e.g., local_addr).
- Extended Socks5Server functionality to expose TCP and UDP
socket creation interfaces for FFI calls.
- Other files: Mostly pass-through logic.
- Added a relatively large Go usage example.
Adds a Linux-only socket_mark u32 config flag (CLI: --socket-mark, env:
ET_SOCKET_MARK, TOML/proto: flags.socket_mark, 0 = disabled) that is
applied as SO_MARK to every outbound underlay socket EasyTier creates:
TCP, UDP, QUIC, WebSocket, WireGuard connectors and listeners, plus the
FakeTCP decoy socket. Lets the host policy-route or filter EasyTier
underlay traffic with 'ip rule fwmark ...' or iptables -m mark.
Plumbing mirrors the existing bind_device pattern:
- FlagsInConfig.socket_mark (proto) + default 0 in gen_default_flags
- bind() builder gets a socket_mark arg; setup_socket2_ext calls
apply_socket_mark which is a no-op for mark=0 and on non-Linux
- TunnelConnector trait gets set_socket_mark(u32) default-no-op method
- IP-based connectors override; create_listener_by_url and the connector
factory pass mark from global_ctx flags
- QUIC threads mark through QuicEndpointManager::{server,connect}
- WebSocket/FakeTCP/TCP default-bind bypass paths apply mark via
socket2::SockRef::from(&tokio_socket)
- ForeignNetworkEntry propagates parent socket_mark into its derived ctx
Includes a Linux smoke test plus a CAP_NET_ADMIN-gated test that does a
getsockopt(SO_MARK) round-trip to confirm the kernel applied the value.
SO_MARK requires CAP_NET_ADMIN; ignored silently on non-Linux. FakeTCP's
TUN-written segments are not covered (kernel doesn't tag raw TUN
writes); operators relying on fwmark for FakeTCP must apply an iptables
rule on the FakeTCP TUN device separately.
Co-authored-by: Claude <noreply@anthropic.com>
Fix the issue where the Magisk module incorrectly matches the lookup main rule in Android 15's cellular network rules, causing data plane connectivity failure
This may helps games to find rooms in virtual network.
- add opt-in Windows UDP broadcast relay config flag and CLI/env plumbing
- capture local UDP broadcasts with Windows raw sockets, normalize packets, and inject them via PeerManager
Stop sharing PeerCenterServer state through a process-global map so local and foreign-network services cannot mix peer-center data when peer ids overlap.