Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TCP networking for target_os = "wasi" #1549

Merged
merged 4 commits into from
Mar 8, 2022

Conversation

haraldh
Copy link
Contributor

@haraldh haraldh commented Feb 15, 2022

With

merged, mio can have limited support for TCP networking for the wasm32-wasi target.

I also modified the tcp_server example.

$ cargo +nightly build --target wasm32-wasi --release --example tcp_server --features="os-poll net"
   Compiling cfg-if v1.0.0
   Compiling wasi v0.10.2+wasi-snapshot-preview1
   Compiling log v0.4.14
   Compiling libc v0.2.112
   Compiling ppv-lite86 v0.2.15
   Compiling wasi v0.11.0+wasi-snapshot-preview1
   Compiling getrandom v0.2.3
   Compiling rand_core v0.6.3
   Compiling env_logger v0.8.4
   Compiling rand_chacha v0.3.1
   Compiling mio v0.8.0 (/home/harald/git/mio)
   Compiling rand v0.8.4
    Finished release [optimized] target(s) in 2.92s

$ wasmtime run --tcplisten 127.0.0.1:9000 --env 'LISTEN_FDS=1' target/wasm32-wasi/release/examples/tcp_server.wasm
Using preopened socket FD 3
You can connect to the server using `nc`:
 $ nc <IP> <PORT>
You'll see our welcome message and anything you type will be printed here.

@haraldh haraldh force-pushed the wasi_mio_upstream branch 2 times, most recently from d821baa to 10a6222 Compare February 15, 2022 12:42
@Thomasdezeeuw
Copy link
Collaborator

Have you actually tested this? Because last I remember my code didn't really work.

@haraldh
Copy link
Contributor Author

haraldh commented Feb 15, 2022

yes I did 😀

@haraldh haraldh changed the title Add networking for target_os = "wasi" Add TCP networking for target_os = "wasi" Feb 17, 2022
@haraldh
Copy link
Contributor Author

haraldh commented Feb 17, 2022

Corrected the tcp_server example build and run instructions.

src/sys/wasi/net.rs Outdated Show resolved Hide resolved
@Thomasdezeeuw
Copy link
Collaborator

@haraldh I just tried the TCP server example, but it doesn't work. Have you tried running the non-wasm version? The non-wasm returns a response on each packet of bytes send, but the wasm only responds when the connection is closed. When using nc you see a response every time yo hit enter (which sends the line you entered), but that doesn't work for the wasm version.

@haraldh
Copy link
Contributor Author

haraldh commented Feb 18, 2022

@haraldh I just tried the TCP server example, but it doesn't work. Have you tried running the non-wasm version? The non-wasm returns a response on each packet of bytes send, but the wasm only responds when the connection is closed. When using nc you see a response every time yo hit enter (which sends the line you entered), but that doesn't work for the wasm version.

You are totally right... how about now with stream.set_nonblocking(true) ??

    pub(crate) fn accept(
        listener: &net::TcpListener,
    ) -> io::Result<(net::TcpStream, net::SocketAddr)> {
        let (stream, addr) = listener.accept()?;
        stream.set_nonblocking(true)?;
        Ok((stream, addr))
    }

@Thomasdezeeuw should now work as expected.

@Thomasdezeeuw
Copy link
Collaborator

@haraldh please don't force push during a review.

@haraldh
Copy link
Contributor Author

haraldh commented Feb 18, 2022

Oops. sorry, didn't know one was happening..

Copy link
Collaborator

@Thomasdezeeuw Thomasdezeeuw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Their are some more problems with this stil.

  • Can't use read and write Interest in a single register call. This is a major issue.
  • Waker not implemented.
  • Selector::try_clone is broken.
  • Still needs UDP implementation.
  • Multiple threads not supported. Not a super big issue I think.

examples/tcp_server.rs Outdated Show resolved Hide resolved
@Thomasdezeeuw
Copy link
Collaborator

I put some review notes and change in Thomasdezeeuw@e530779.

@npmccallum
Copy link

npmccallum commented Feb 18, 2022

Their are some more problems with this stil.

  • Can't use read and write Interest in a single register call. This is a major issue.
  • Waker not implemented.
  • Selector::try_clone is broken.
  • Still needs UDP implementation.
  • Multiple threads not supported. Not a super big issue I think.

WebAssembly has no threads. Therefore, at least some of these issues don't apply. For example, what is the point of implementing Waker if there is only one thread?

WASI has no UDP support. Only streams are supported at this time.

@Thomasdezeeuw
Copy link
Collaborator

Thomasdezeeuw commented Feb 18, 2022

Their are some more problems with this stil.

  • Can't use read and write Interest in a single register call. This is a major issue.
  • Waker not implemented.
  • Selector::try_clone is broken.
  • Still needs UDP implementation.
  • Multiple threads not supported. Not a super big issue I think.

WebAssembly has no threads. Therefore, at least some of these issues don't apply. For example, what is the point of implementing Waker if there is only one thread?

Isn't that something in the pipeline? I don't remember the details of it, but I thought it was, but last I checked was a couple of years ago.

WASI has no UDP support. Only streams are supported at this time.

Ok.

So then we have:

  • Can't use read and write Interest in a single register call. This is still a major issue.
  • Waker not implemented. We'll need to remove the public type.
  • Selector::try_clone is broken. We could remove the implementation for now.
  • Still needs UDP implementation.
  • Multiple threads not supported. Not a super big issue I think.

Could you cfg out the things that don't make sense for wasm, like the Waker type.

@npmccallum
Copy link

Their are some more problems with this stil.

  • Can't use read and write Interest in a single register call. This is a major issue.
  • Waker not implemented.
  • Selector::try_clone is broken.
  • Still needs UDP implementation.
  • Multiple threads not supported. Not a super big issue I think.

WebAssembly has no threads. Therefore, at least some of these issues don't apply. For example, what is the point of implementing Waker if there is only one thread?

Isn't that something in the pipeline? I don't remember the details of it, but I thought it was, but last I checked was a couple of years ago.

The spec isn't finalized yet. Portions of the proposal have been implemented in some runtimes. But WASI has no official way to spawn yet.

@haraldh
Copy link
Contributor Author

haraldh commented Feb 21, 2022

@Thomasdezeeuw thanks for your review. I merged your PR and added additional cfg according to your comments.

Also added more cfg, so that cargo hack test --feature-powerset also works with:

$ CARGO_TARGET_WASM32_WASI_RUNNER="wasmtime run" cargo +nightly hack test --target wasm32-wasi --feature-powerset

src/net/tcp/listener.rs Outdated Show resolved Hide resolved
examples/udp_server.rs Outdated Show resolved Hide resolved
examples/udp_server.rs Show resolved Hide resolved
examples/tcp_server.rs Outdated Show resolved Hide resolved
examples/tcp_server.rs Outdated Show resolved Hide resolved
src/sys/wasi/mod.rs Outdated Show resolved Hide resolved
src/sys/wasi/mod.rs Outdated Show resolved Hide resolved
src/sys/wasi/mod.rs Outdated Show resolved Hide resolved
src/sys/wasi/mod.rs Outdated Show resolved Hide resolved
@haraldh
Copy link
Contributor Author

haraldh commented Mar 1, 2022

pushed more commits to be squashed in the end

@npmccallum
Copy link

@Thomasdezeeuw Any chance we can merge this? Are we waiting for something?

Copy link
Collaborator

@Thomasdezeeuw Thomasdezeeuw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One final nit, but otherwise LGTM.

If you don't get to the final change @haraldh I'll do it tonight and merge the pr.

@@ -1,19 +1,17 @@
// You can run this example from the root of the mio repo:
// cargo run --example tcp_server --features="os-poll net"
use mio::event::Event;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you revert all changes here, the changes make the example much harder to read. Please use the same structure as for the UDP example, with the extra main. I know it will generate a number of warnings, but that's OK.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, will do

haraldh and others added 2 commits March 8, 2022 18:27
Based on tokio-rs#1395

And with
* bytecodealliance/wasmtime#3711
* rust-lang/rust#93158
merged, mio can have limited support for networking for the
`wasm32-wasi` target.

Co-authored-by: Thomas de Zeeuw <thomasdezeeuw@gmail.com>
Signed-off-by: Harald Hoyer <harald@profian.com>
Signed-off-by: Harald Hoyer <harald@profian.com>
@haraldh
Copy link
Contributor Author

haraldh commented Mar 8, 2022

@Thomasdezeeuw squashed and left the old examples alone

@haraldh
Copy link
Contributor Author

haraldh commented Mar 8, 2022

oh... you wanted it like UDP.. will change the examples.

Otherwise `cargo test` fails.

Signed-off-by: Harald Hoyer <harald@profian.com>
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 --target wasm32-wasi --release --example tcp_listenfd_server --features="os-poll net"
   Compiling cfg-if v1.0.0
   Compiling wasi v0.10.2+wasi-snapshot-preview1
   Compiling log v0.4.14
   Compiling libc v0.2.112
   Compiling ppv-lite86 v0.2.15
   Compiling wasi v0.11.0+wasi-snapshot-preview1
   Compiling getrandom v0.2.3
   Compiling rand_core v0.6.3
   Compiling env_logger v0.8.4
   Compiling rand_chacha v0.3.1
   Compiling mio v0.8.0 (/home/harald/git/mio)
   Compiling rand v0.8.4
    Finished release [optimized] target(s) in 2.92s

$ wasmtime run --tcplisten 127.0.0.1:9000 --env 'LISTEN_FDS=1' target/wasm32-wasi/release/examples/tcp_listenfd_server.wasm
Using preopened socket FD 3
You can connect to the server using `nc`:
 $ nc <IP> <PORT>
You'll see our welcome message and anything you type will be printed here.
```

Signed-off-by: Harald Hoyer <harald@profian.com>
@haraldh
Copy link
Contributor Author

haraldh commented Mar 8, 2022

ok, ready to be merged, except if you want to squash all commits.

@Thomasdezeeuw Thomasdezeeuw merged commit b2bbc10 into tokio-rs:master Mar 8, 2022
@npmccallum
Copy link

@Thomasdezeeuw Thanks! When can we get this in a release so that we can start working on the higher level components?

@Thomasdezeeuw
Copy link
Collaborator

Thanks @haraldh and @npmccallum for the work (and the patience).

@Thomasdezeeuw Thanks! When can we get this in a release so that we can start working on the higher level components?

Yes, I would like to include #1551 as well, so I think we can make a release this week.

@Thomasdezeeuw Thomasdezeeuw mentioned this pull request Mar 11, 2022
@Rustin170506
Copy link

I can't seem to run it in a non-wasm environment anymore. How should I run this example on macos?

@Thomasdezeeuw
Copy link
Collaborator

Did you follow the instruction in the example?

// cargo +nightly build --target wasm32-wasi --example tcp_listenfd_server --features="os-poll net"
// wasmtime run --tcplisten 127.0.0.1:9000 --env 'LISTEN_FDS=1' target/wasm32-wasi/debug/examples/tcp_server.wasm

That run for me on macOS. If it doesn't work for you can you provide some more details such as the error you're seeing.

@haraldh
Copy link
Contributor Author

haraldh commented Mar 19, 2022

Oh, yeah the non-wasi version needs some update.

@Rustin170506
Copy link

What is the purpose of our setting LISTEN_FDS here? We don't seem to be using this value.

@Thomasdezeeuw
Copy link
Collaborator

What is the purpose of our setting LISTEN_FDS here? We don't seem to be using this value.

The $LISTEN_FDS env var is a commonly used init systems, such as systemd, to indicate opened file descriptors (outside of standard in/out/err).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants