#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn main() {
use std::io::{Read, Write};
use std::time::Duration;
let dest = std::env::args()
.nth(1)
.unwrap_or_else(|| "/tmp/net-vm".to_string());
eprintln!("=== bake alpine + start (TSI kernel) ===");
let image = supermachine::Image::bake_kvm_auto("alpine", &dest).expect("bake_kvm_auto");
let vm = image
.start(&supermachine::VmConfig::new())
.expect("Image::start");
std::thread::sleep(Duration::from_millis(6000));
eprintln!("=== EGRESS: wget http://example.com/ (DNS over TSI) ===");
let e = vm
.exec_builder()
.argv([
"/bin/sh",
"-c",
"wget -q -T 15 -O- http://example.com/ 2>&1 | grep -o '<title>[^<]*</title>' | head -1; echo RC=$?",
])
.output()
.expect("exec wget");
eprintln!(
"EGRESS success={} out={:?}",
e.success(),
String::from_utf8_lossy(&e.stdout).trim_end()
);
eprintln!("=== INGRESS: start guest httpd :8080, expose to host ===");
let _srv = vm
.exec([
"/bin/sh",
"-c",
"while :; do printf 'HTTP/1.0 200 OK\\r\\nContent-Length: 13\\r\\n\\r\\nsm-ingress-ok' \
| /bin/busybox nc -l -p 8080; done",
])
.expect("spawn server");
std::thread::sleep(Duration::from_millis(1500));
let dbg = vm
.exec_builder()
.argv([
"/bin/sh",
"-c",
"echo --listen--; /bin/busybox netstat -ltn 2>/dev/null | grep -E '8080|Proto'",
])
.output()
.expect("exec dbg");
eprintln!(
"[guest] {}",
String::from_utf8_lossy(&dbg.stdout).trim_end()
);
let fwd = vm.expose_tcp(0, 8080).expect("expose_tcp");
let addr = fwd.local_addr();
eprintln!("host forwarder on {addr} -> guest :8080");
let mut got = String::new();
match std::net::TcpStream::connect(addr) {
Ok(mut s) => {
s.set_read_timeout(Some(Duration::from_secs(8))).ok();
let _ = s.write_all(b"GET / HTTP/1.0\r\nHost: x\r\n\r\n");
let _ = s.read_to_string(&mut got);
}
Err(err) => eprintln!("INGRESS connect error: {err}"),
}
let ingress_ok = got.contains("sm-ingress-ok");
eprintln!(
"INGRESS ok={ingress_ok} response_tail={:?}",
got.lines().last().unwrap_or("")
);
drop(fwd);
vm.stop().expect("stop");
eprintln!("=== done ===");
}
#[cfg(not(all(target_os = "linux", target_arch = "x86_64")))]
fn main() {
eprintln!("kvm_net is Linux/x86_64 only");
}