Add thread spawning FFI
This commit is contained in:
parent
a2cbd2ad77
commit
1b69b4a8e1
7 changed files with 98 additions and 29 deletions
|
|
@ -4,23 +4,15 @@ import OSLog
|
||||||
|
|
||||||
class PacketTunnelProvider: NEPacketTunnelProvider {
|
class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||||
let logger = Logger(subsystem: "com.hackclub.burrow", category: "General")
|
let logger = Logger(subsystem: "com.hackclub.burrow", category: "General")
|
||||||
|
var osInitialized = false
|
||||||
|
|
||||||
override func startTunnel(options: [String: NSObject]?, completionHandler: @escaping (Error?) -> Void) {
|
override func startTunnel(options: [String: NSObject]?, completionHandler: @escaping (Error?) -> Void) {
|
||||||
libburrow.initialize_oslog()
|
if(!osInitialized){
|
||||||
let fild = libburrow.retrieve()
|
libburrow.initialize_oslog()
|
||||||
if fild == -1 {
|
osInitialized=true
|
||||||
// Not sure if this is the right way to return an error
|
|
||||||
logger.error("Failed to retrieve file descriptor for burrow.")
|
|
||||||
let err = NSError(
|
|
||||||
domain: "com.hackclub.burrow",
|
|
||||||
code: 1_010,
|
|
||||||
userInfo: [NSLocalizedDescriptionKey: "Failed to find TunInterface"]
|
|
||||||
)
|
|
||||||
completionHandler(err)
|
|
||||||
}
|
}
|
||||||
logger.info("fd: \(fild)")
|
libburrow.spawn_server()
|
||||||
let network_settings = genNetSec(fild: fild)
|
logger.debug("spawned server")
|
||||||
logger.info("Network Settings: - ipv4:\(network_settings.ipv4Settings) -mtu: \(network_settings.mtu)")
|
|
||||||
completionHandler(nil)
|
completionHandler(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,3 +9,4 @@ typedef struct {
|
||||||
|
|
||||||
NetWorkSettings getNetworkSettings(int);
|
NetWorkSettings getNetworkSettings(int);
|
||||||
void initialize_oslog();
|
void initialize_oslog();
|
||||||
|
void spawn_server();
|
||||||
|
|
|
||||||
11
Cargo.lock
generated
11
Cargo.lock
generated
|
|
@ -1136,6 +1136,16 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_cpus"
|
||||||
|
version = "1.16.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi 0.3.1",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.17.1"
|
version = "1.17.1"
|
||||||
|
|
@ -1768,6 +1778,7 @@ dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"libc",
|
"libc",
|
||||||
"mio",
|
"mio",
|
||||||
|
"num_cpus",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ edition = "2021"
|
||||||
crate-type = ["lib", "staticlib"]
|
crate-type = ["lib", "staticlib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tokio = { version = "1.21", features = ["rt", "macros"] }
|
tokio = { version = "1.21", features = ["rt", "rt-multi-thread", "macros"] }
|
||||||
tun = { version = "0.1", path = "../tun" , features = ["tokio"]}
|
tun = { version = "0.1", path = "../tun" , features = ["tokio"]}
|
||||||
clap = { version = "4.3.2", features = ["derive"] }
|
clap = { version = "4.3.2", features = ["derive"] }
|
||||||
env_logger = "0.10"
|
env_logger = "0.10"
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ use tun::TunInterface;
|
||||||
#[cfg(target_vendor = "apple")]
|
#[cfg(target_vendor = "apple")]
|
||||||
pub use apple::{NetWorkSettings, getNetworkSettings, initialize_oslog};
|
pub use apple::{NetWorkSettings, getNetworkSettings, initialize_oslog};
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
|
||||||
|
pub use server::spawn_server;
|
||||||
// TODO Separate start and retrieve functions
|
// TODO Separate start and retrieve functions
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
|
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
|
||||||
|
|
@ -48,3 +50,22 @@ pub extern "C" fn retrieve() -> i32 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_iface() -> Option<TunInterface> {
|
||||||
|
(1..100)
|
||||||
|
.filter_map(|i| {
|
||||||
|
debug!("Getting TunInterface with fd: {:?}", i);
|
||||||
|
let iface = unsafe { TunInterface::from_raw_fd(i) };
|
||||||
|
match iface.name() {
|
||||||
|
Ok(name) => {
|
||||||
|
debug!("Found interface {}", name);
|
||||||
|
Some(iface)
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
mem::forget(iface);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.next()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,25 +2,72 @@ use axum::{body::Bytes, error_handling::HandleErrorLayer, extract::{DefaultBodyL
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
sync::{Arc, RwLock},
|
sync::Arc,
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
use tokio::sync::RwLock;
|
||||||
|
use tokio::runtime::Runtime;
|
||||||
use std::net::{Ipv4Addr, SocketAddr};
|
use std::net::{Ipv4Addr, SocketAddr};
|
||||||
use axum::handler::HandlerWithoutStateExt;
|
use axum::handler::HandlerWithoutStateExt;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use tun::TunInterface; // TODO: refactor to tokio TunInterface, which doesn't implement `Send`
|
use tun::tokio::TunInterface; // TODO: refactor to tokio TunInterface, which doesn't implement `Send`
|
||||||
|
use std::thread;
|
||||||
|
use crate::get_iface;
|
||||||
|
use tracing::{info, debug, error};
|
||||||
|
|
||||||
type SharedState = Arc<RwLock<TunInterface>>;
|
type SharedState = Arc<RwLock<TunInterface>>;
|
||||||
|
|
||||||
pub async fn serve(ti: TunInterface){
|
#[no_mangle]
|
||||||
let state = Arc::new(RwLock::new(
|
pub extern "C" fn spawn_server(){
|
||||||
ti
|
info!("Spawning server");
|
||||||
));
|
let ti = get_iface().unwrap();
|
||||||
|
debug!("Got interface");
|
||||||
|
let rt = Runtime::new().unwrap();
|
||||||
|
let _handle = thread::spawn(move || {
|
||||||
|
rt.spawn(async {
|
||||||
|
service(ti).await;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
debug!("Spawned thread: finish spawn server");
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn service(ti: crate::TunInterface){
|
||||||
|
info!("Spawning service");
|
||||||
|
let shared_state = Arc::new(RwLock::new(TunInterface::new(ti).unwrap()));
|
||||||
|
info!("Created shared state");
|
||||||
|
let state_cl= shared_state.clone();
|
||||||
|
let lp = tokio::spawn(
|
||||||
|
async move {
|
||||||
|
burrow_loop(state_cl).await;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
let srv = tokio::spawn(
|
||||||
|
async move {
|
||||||
|
serve(shared_state).await;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
info!("Created threads");
|
||||||
|
tokio::join!(lp, srv);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn burrow_loop(state: SharedState){
|
||||||
|
debug!("loop called");
|
||||||
|
let mut buf = [0u8; 1504];
|
||||||
|
loop {
|
||||||
|
let n = state.write().await.read(&mut buf[..]).await.unwrap();
|
||||||
|
// do something with the data
|
||||||
|
info!("read {} bytes", n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn serve(state: SharedState){
|
||||||
|
debug!("serve called");
|
||||||
let app_router = Router::new()
|
let app_router = Router::new()
|
||||||
.route("/info", get(network_settings))
|
.route("/info", get(network_settings))
|
||||||
.with_state(state);
|
.with_state(state);
|
||||||
let port = std::env::var("BURROW_PORT").unwrap_or("3000".to_string());
|
let port = std::env::var("BURROW_PORT").unwrap_or("3000".to_string());
|
||||||
let sock_addr = SocketAddr::new(Ipv4Addr::LOCALHOST.into(), port.parse().unwrap());
|
let sock_addr = SocketAddr::new(Ipv4Addr::LOCALHOST.into(), port.parse().unwrap());
|
||||||
|
info!("Listening on {}...", sock_addr);
|
||||||
axum::Server::bind(&sock_addr)
|
axum::Server::bind(&sock_addr)
|
||||||
.serve(app_router.into_make_service())
|
.serve(app_router.into_make_service())
|
||||||
.await
|
.await
|
||||||
|
|
@ -28,11 +75,11 @@ pub async fn serve(ti: TunInterface){
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_handler]
|
#[debug_handler]
|
||||||
async fn network_settings(State(state): State<SharedState>) -> impl IntoResponse{
|
async fn network_settings(State(state): State<SharedState>) -> impl IntoResponse {
|
||||||
let st = state.read().unwrap();
|
let st = state.read().await;
|
||||||
let name = st.name().unwrap();
|
let name = st.name().await.unwrap();
|
||||||
let mtu = st.mtu().unwrap();
|
let mtu = st.mtu().await.unwrap();
|
||||||
let netmask = st.netmask().unwrap();
|
let netmask = st.netmask().await.unwrap();
|
||||||
let res = Json(json!({
|
let res = Json(json!({
|
||||||
"name": name,
|
"name": name,
|
||||||
"mtu": mtu,
|
"mtu": mtu,
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,6 @@ pub struct TunInterface {
|
||||||
inner: AsyncFd<crate::TunInterface>,
|
inner: AsyncFd<crate::TunInterface>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for TunInterface {
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TunInterface {
|
impl TunInterface {
|
||||||
pub fn new(tun: crate::TunInterface) -> io::Result<Self> {
|
pub fn new(tun: crate::TunInterface) -> io::Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue