ktock / container2wasm

Container to WASM converter
https://ktock.github.io/container2wasm-demo/
Apache License 2.0
2.07k stars 85 forks source link

[Networking] True async without Atomics #349

Open gregnr opened 1 week ago

gregnr commented 1 week ago

Amazing work on this project - it's no easy feat getting all of these layers to work together in a simple way.

I built a user space TCP/IP JS library (via WASM bindings to lwIP) for use cases like communicating with emulators via L2 frames and exposing a nice TCP interface to the developer (running in the browser). I originally built it in Go using gvisor's tcpip stack but later rewrote to use lwIP which is much smaller and avoids bundling the Go runtime in the WASM file.

I've been trying to find a way to connect this with c2w so that devs can communicate with the container via TCP/IP in the browser. So far I am:

IIUC, poll_oneoff is expected to be a synchronous blocking call which your example accomplishes via SharedArrayBuffer + Atomic APIs within a worker. The trouble with these APIs is that they limit a large number of developers due to cross origin header security requirements which many developers don't have control over.

I'm trying to see if there is any possible way to implement this asynchronously from the JS side. My understanding is that this type of thing is usually accomplished by compiling the WASM using some form of asyncify. I noticed that you use Binaryen's asyncify pass in both Bochs and TinyEMU to implement setjmp and longjmp, but this is where my understanding ends. Can we somehow use jumps/trampolining/unwinding or similar to asyncify poll_oneoff? Or maybe something else entirely?

Hope this makes sense and looking forward to hearing your thoughts.

ktock commented 1 week ago

I guess your design might work though I haven't tried it. An example implementation is: poll_oneoff wrapper can start unwind (maybe with saving args to somewhere JS can easily access) instead of calling the imported function. wasm_start needs to return to the caller JS so that JS code can do anything needed to handle poll_oneoff. Then JS code calls Bochs again then it should rewind to the poll_oneoff wrapper.

gregnr commented 1 week ago

Thanks for the quick reply. This approach makes sense - I'll see if I can make it work.