CympleTech / chamomile

Lightweight p2p library. Support build robust connection on decentralized network.
Apache License 2.0
111 stars 18 forks source link

Possibility of WASM Support? #18

Open zicklag opened 3 years ago

zicklag commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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:

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 commented 3 years ago

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

sunhuachuang commented 3 years ago

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

zicklag commented 3 years ago

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 commented 3 years ago

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());
        }
    });
}