Skip to content

Commit 10a6222

Browse files
committed
Modify the tcp_server example to support target_os = "wasi"
Use the `LISTEN_FDS` mechanism to use pre-opened sockets. Especially for `wasm32-wasi` there is no other way to get access to sockets, than to use pre-opened sockets. Because `wasm32-wasi` does not yet return `TcpListener::local_addr()`, an unspecified IP address and port will be returned and displayed. ``` $ cargo +nightly build --release --example tcp_server --features="os-poll net" Compiling ppv-lite86 v0.2.15 Compiling getrandom v0.2.3 Compiling mio v0.8.0 (/home/harald/git/mio) Compiling env_logger v0.8.4 Compiling rand_core v0.6.3 Compiling rand_chacha v0.3.1 Compiling rand v0.8.4 Finished release [optimized] target(s) in 1.75s $ wasmtime run --tcplisten 127.0.0.1:9000 --env 'LISTEN_FDS=1' target/wasm32-wasi/debug/examples/tcp_server.wasm ``` Signed-off-by: Harald Hoyer <[email protected]>
1 parent 7aaaf55 commit 10a6222

File tree

1 file changed

+40
-11
lines changed

1 file changed

+40
-11
lines changed

examples/tcp_server.rs

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,24 @@ const SERVER: Token = Token(0);
1313
// Some data we'll send over the connection.
1414
const DATA: &[u8] = b"Hello world!\n";
1515

16+
#[cfg(not(windows))]
17+
fn get_first_listen_fd_listener() -> Option<std::net::TcpListener> {
18+
#[cfg(unix)]
19+
use std::os::unix::io::FromRawFd;
20+
#[cfg(target_os = "wasi")]
21+
use std::os::wasi::io::FromRawFd;
22+
23+
let stdlistener = unsafe { std::net::TcpListener::from_raw_fd(3) };
24+
stdlistener.set_nonblocking(true).unwrap();
25+
Some(stdlistener)
26+
}
27+
28+
#[cfg(windows)]
29+
fn get_first_listen_fd_listener() -> Option<std::net::TcpListener> {
30+
// Windows does not support `LISTEN_FDS`
31+
None
32+
}
33+
1634
fn main() -> io::Result<()> {
1735
env_logger::init();
1836

@@ -22,8 +40,26 @@ fn main() -> io::Result<()> {
2240
let mut events = Events::with_capacity(128);
2341

2442
// Setup the TCP server socket.
25-
let addr = "127.0.0.1:9000".parse().unwrap();
26-
let mut server = TcpListener::bind(addr)?;
43+
let mut server = {
44+
if std::env::var("LISTEN_FDS").is_ok() && cfg!(not(windows)) {
45+
let stdlistener = get_first_listen_fd_listener().unwrap();
46+
println!("Using preopened socket FD 3");
47+
println!("You can connect to the server using `nc`:");
48+
match stdlistener.local_addr() {
49+
Ok(a) => println!(" $ nc {} {}", a.ip(), a.port()),
50+
Err(_) => println!(" $ nc <IP> <PORT>"),
51+
}
52+
println!("You'll see our welcome message and anything you type will be printed here.");
53+
TcpListener::from_std(stdlistener)
54+
} else {
55+
let addr = "127.0.0.1:9000".parse().unwrap();
56+
let listener = TcpListener::bind(addr)?;
57+
println!("You can connect to the server using `nc`:");
58+
println!(" $ nc 127.0.0.1 9000");
59+
println!("You'll see our welcome message and anything you type will be printed here.");
60+
listener
61+
}
62+
};
2763

2864
// Register the server with poll we can receive events for it.
2965
poll.registry()
@@ -34,10 +70,6 @@ fn main() -> io::Result<()> {
3470
// Unique token for each incoming connection.
3571
let mut unique_token = Token(SERVER.0 + 1);
3672

37-
println!("You can connect to the server using `nc`:");
38-
println!(" $ nc 127.0.0.1 9000");
39-
println!("You'll see our welcome message and anything you type will be printed here.");
40-
4173
loop {
4274
poll.poll(&mut events, None)?;
4375

@@ -65,11 +97,8 @@ fn main() -> io::Result<()> {
6597
println!("Accepted connection from: {}", address);
6698

6799
let token = next(&mut unique_token);
68-
poll.registry().register(
69-
&mut connection,
70-
token,
71-
Interest::READABLE.add(Interest::WRITABLE),
72-
)?;
100+
poll.registry()
101+
.register(&mut connection, token, Interest::WRITABLE)?;
73102

74103
connections.insert(token, connection);
75104
},

0 commit comments

Comments
 (0)