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

Possibility of WASM Support? #18

Open
zicklag opened this issue Apr 27, 2021 · 7 comments
Open

Possibility of WASM Support? #18

zicklag opened this issue Apr 27, 2021 · 7 comments

Comments

@zicklag
Copy link

zicklag commented Apr 27, 2021

Hey there, I just found this and I was wondering what your thoughts on the possibility of WASM support might be. A quick check and attempt at compiling leads me to think that the only thing stopping it so far is its dependency on async-io from the smol crate.

For web we might be able to get away without smol by using wasm-bindgen-futures and I recently ported async_lock to work on web ( it just needed to remove the dependency on std::instant ) so we might be able to get async_channel to work as well ( or it will just work, I haven't tried it.

At that point you just have to worry about the transport. You would have to use websockets I think, and peer to peer doesn't really work on web without a signalling server we would have to take that into account to.

Anyway, I literally just found this, but I thought it looked neat and I've wondered about having a Rust library that I could on desktop native and in web to provide peer-to-peer DApps for a while so I thought I'd ask. :)

@sunhuachuang
Copy link
Member

Yes, it would be pretty cool.
I know little about WASM, and my main confusion at the moment is the TCP/UDP in the async-io, if it can be resolved, and other problems are not big. and signalling server or relay server it not problem, now in the code, have relay feature and hole punching (not complete yet). And we had built a project: ESSE, mobile and desktop client has run perfect when use relay service.
We can discuss and try more about it. Can you help us try together ?

@zicklag
Copy link
Author

zicklag commented Apr 28, 2021

Awesome!

I can't make any guarantees about time I'll have for this, but I think I'll be able to try it out. :)

When I get the chance I'll try to see if I can get it to build on web.

I'm currently building a game engine that runs on desktop and web so I've been learning about how to make Rust run in web.

@zicklag
Copy link
Author

zicklag commented May 12, 2021

I just started looking into this a little bit and my initial observation is that both disk access and network access are built-in to chamomile and not optional. Also the network transports are hard-coded to UDP, TCP, RTP, and UDT.

Here's my initial thought on how we might change this to make it more universal and to make it easier to support web:

I'm thinking that we should create two traits: Database and Transport:

  • The Database trait would be an abstraction that allows you to store the peer key and the peer list that is currently stored on disk. By allowing different implementations of the Database trait, we can include out-of-the box support for storing the database information on disk, and users could also provide their own implementations. Implementations could do stuff like use browser local storage when targeting web, or use the system keyring to store the peer key, etc. ( not sure if the keyring thing is a good idea, but for example's sake )
  • Similarly we would have a Transport trait that we would provide out-of-the-box implementations for TCP, etc., but users could also write their own transports, allowing them to communicate over protocol that they could send bytes over. Again, this would help us target web by allowing us to implement a Transport that works over web-sockets.

Using traits for this wouldn't be necessary, but I think it would be great for making the architecture more flexible and allowing it to adapt to more use-cases.

What do you think? I haven't gotten deep into this so I could be missing things.

@sunhuachuang
Copy link
Member

Yes, you are right. Core problem is Database and Transport.

  • Database maybe easier to solve, we can add feature or trait to solve.
  • Transport. The current transport has been completely decoupled from the upper, and only needs this transport to meet the defined Message(./src/transports.rs TransportSendMessage, TransportRecvMessage). Similar to the mailbox in the Actor model, no matter what the inside of the Actor looks like, whether it is based on the socket of the system, or what. Only sending and receiving of the Message by the mailbox is required.
    Therefore, the most important thing is to ensure that async_channel can be used normally in the web.

@sunhuachuang
Copy link
Member

Reference, see wasm support in smol. smol-rs/smol#87

@zicklag
Copy link
Author

zicklag commented May 12, 2021

Therefore, the most important thing is to ensure that async_channel can be used normally in the web.

Perfect. I just compiled async_channel for the web without problems, but I'll have to test actually running it to make sure it works.

Reference, see wasm support in smol. smol-rs/smol#87

Thanks. I don't think smol is going to run directly on web anytime soon, but I think we might not need to. While not as flexible as a normal executor like smol ( you can't wait for spawned tasks to complete, they always act like they are detached() ), you can use wasm-bindgen-futures::spawn_local() to spawn background tasks on WASM which I think will be sufficient for what we need in chamomile.

After ensuring that async-channel will run on WASM I'll starting working on moving Database and Transport over to traits and then trying to make WASM compatible implementations of them using browser local storage for Database and websockets for WASM.

When we should be able to run relay servers that host a websocket port and a normal TCP port to enable hooking web clients up to non-web clients seamlessly.

@zicklag
Copy link
Author

zicklag commented May 13, 2021

A simple send and receive test shows that async-channel works on web!

use wasm_bindgen_futures::spawn_local;
use web_sys::console;

fn main() {
    spawn_local(async move {
        let (sender, receiver) = async_channel::unbounded();

        spawn_local(async move {
            for i in 0..=10usize {
                console::log_1(&format!("sending: {}", i).into());
                sender.send(i).await.ok();
            }
        });

        while let Ok(i) = receiver.recv().await {
            console::log_1(&format!("received: {}", i).into());
        }
    });
}

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

No branches or pull requests

2 participants