feat: Add data plane support to FFI (#2287)

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.
This commit is contained in:
w568w
2026-06-04 17:17:41 +08:00
committed by GitHub
parent e3ca7ffa54
commit e0745f4bab
14 changed files with 2336 additions and 21 deletions
+55
View File
@@ -1,3 +1,5 @@
#[cfg(feature = "ffi-dataplane")]
use crate::launcher::{DataPlaneTcpListener, DataPlaneTcpStream, DataPlaneUdpSocket};
use dashmap::DashMap;
use std::fmt::{Display, Formatter};
use std::{collections::BTreeMap, path::PathBuf, sync::Arc};
@@ -171,6 +173,59 @@ impl NetworkInstanceManager {
tokio::runtime::Runtime::new()?.block_on(self.collect_network_infos())
}
#[cfg(feature = "ffi-dataplane")]
pub async fn data_plane_tcp_connect(
&self,
instance_id: &uuid::Uuid,
dst_addr: std::net::SocketAddr,
timeout: std::time::Duration,
) -> Result<DataPlaneTcpStream, anyhow::Error> {
let instance = self
.instance_map
.get(instance_id)
.ok_or_else(|| anyhow::anyhow!("instance {} not found", instance_id))?;
instance.data_plane_tcp_connect(dst_addr, timeout).await
}
#[cfg(feature = "ffi-dataplane")]
pub async fn data_plane_tcp_bind(
&self,
instance_id: &uuid::Uuid,
local_port: u16,
timeout: std::time::Duration,
) -> Result<DataPlaneTcpListener, anyhow::Error> {
let instance = self
.instance_map
.get(instance_id)
.ok_or_else(|| anyhow::anyhow!("instance {} not found", instance_id))?;
instance.data_plane_tcp_bind(local_port, timeout).await
}
#[cfg(feature = "ffi-dataplane")]
pub async fn data_plane_udp_bind(
&self,
instance_id: &uuid::Uuid,
local_port: u16,
timeout: std::time::Duration,
) -> Result<DataPlaneUdpSocket, anyhow::Error> {
let instance = self
.instance_map
.get(instance_id)
.ok_or_else(|| anyhow::anyhow!("instance {} not found", instance_id))?;
instance.data_plane_udp_bind(local_port, timeout).await
}
#[cfg(feature = "ffi-dataplane")]
pub fn data_plane_wait_runtime_handle(
&self,
instance_id: &uuid::Uuid,
timeout: std::time::Duration,
) -> Option<tokio::runtime::Handle> {
self.instance_map
.get(instance_id)
.and_then(|inst| inst.wait_runtime_handle(timeout))
}
pub async fn get_network_info(
&self,
instance_id: &uuid::Uuid,