Giter Club home page Giter Club logo

Comments (35)

meejah avatar meejah commented on May 24, 2024 2

The Winden servers that LeastAuthority.com runs support WebSocket (indeed, https://winden.app is a Web client using WASM etc). The addresses are in the FAQ in the linked app, and are currently wss://mailbox.mw.leastauthority.com/v1 and wss://relay.mw.leastauthority.com / tcp://relay.mw.leastauthority.com:4001 for the relay.

Note that a "tcp-only" client can talk to a "websocket-only" client via that relay too.

from magic-wormhole.rs.

andipabst avatar andipabst commented on May 24, 2024 1

@piegamesde Thanks for your support!
I had a look at it and could get rid of most errors by either ripping the code out or using cargo feature flags, as you suggested.

Now the only thing left is the direct TCP Connection in transit.rs. How should this be approached? Maybe this could be implemented using Websockets and I also thought about using WebRTC for the communication. But I think in the end the transit relay might have to be adapted for this (e.g. to not only handle tcp connections, but also websocket connections).
Or do you have another idea or concept?

from magic-wormhole.rs.

piegamesde avatar piegamesde commented on May 24, 2024 1

Now the only thing left is the direct TCP Connection in transit.rs. […] in the end the transit relay might have to be adapted for this

Indeed. We are in the process of extending the relay protocol to support WebSockets connections in addition to plain TCP. Some links that may help you with this:

For a start, I suggest that you simply hardcode the default relay server and ignore the rest, as we already know that it supports WebSockets. Once it works, we can talk about implementing the necessary protocol extensions (I'd be willing to help with that).

from magic-wormhole.rs.

andipabst avatar andipabst commented on May 24, 2024 1

No worries. I totally agree with you, but when serving the website over https (which should definitely be done), browsers also require using secure websocket connections. (See e.g. https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications#security_considerations)

from magic-wormhole.rs.

piegamesde avatar piegamesde commented on May 24, 2024 1

Thanks for explaining. wss://piegames.de/wormhole-transit-relay should now work too

from magic-wormhole.rs.

Sky-NiniKo avatar Sky-NiniKo commented on May 24, 2024 1

It works! Thank you everyone.
PS: @meejah it is an interesting project thank you for the discovery.

from magic-wormhole.rs.

warner avatar warner commented on May 24, 2024

WASM is great. Yeah, maybe we write the "wormhole core" approach (in #1) in a way that can be compiled to wasm, and then the IO wrapper gets written in JS (since wasm is a purely computational environment, and has no IO except exchanging messages with its host).

from magic-wormhole.rs.

warner avatar warner commented on May 24, 2024

Mind you, the amount of JS you'd need to write for the platform-specific IO layer might be considerable..

from magic-wormhole.rs.

warner avatar warner commented on May 24, 2024

Does this require nostd? Or providing a memory allocator of some sort?

from magic-wormhole.rs.

warner avatar warner commented on May 24, 2024

I started experimenting with this over the weekend. Two stumbling blocks I've hit so far:

  • we use sodiumoxide, and of course that must compile a large C library, which fails under WASM. We're only using it for SecretBox, so I think we can replace this with the libsodium-compatible XChaCha20Poly1305 support that was recently added to the chacha20poly1305 crate (under the RustCrypto AEADs umbrella). #58 is the place for this.
  • the magic-wormhole -> spake2 -> curve25519-dalek -> clear_on_drop dependency pathway gets us a clear_on_drop crate that uses a C file to do some assembly-language tricks to zeroize dropped secret-key buffers. It has a feature flag (no_cc) to disable this, but it's not our direct dependency (yet: #63). So we'd need a way to ask spake2 to set a flag that asks curve25519-dalek to set a flag that asks clear_on_drop to avoid the C compile.

I don't know what other problems we'll hit. I was able to bypass the first one by just replacing all our symmetric crypto with no-ops, but I don't know how to get past the second one. Maybe there's some Cargo.toml/Cargo.lock wizardry that lets you set features for a transitive-dependency? Or maybe I should check out local copies of the whole dependency chain, and modify all of their Cargo.toml's to use path= dependencies on everything, so I can edit it all in-place.

from magic-wormhole.rs.

warner avatar warner commented on May 24, 2024

Once we get the core library compiling to WASM, the next step is to write JS glue code to satisfy its IO needs. The core is written as a function that accepts "events" from the outside world, and returns a list of actions. The application-facing API consists of API events like AllocateCode and Send, and result actions like GotCode and GotMessage. When the core needs IO to be performed, it returns an action like WebSocketOpen, and expects to eventually be given an event like WebSocketConnectionMade and WebSocketMessageReceived:

https://github.com/warner/magic-wormhole.rs/blob/a8b9cc32d9ccaca6a08de9d9f547adc9129f1d53/src/core/api.rs#L169-L186

So the JS glue needs to react to these actions with things like new WebSocket(url) and wiring up the handlers to deliver inbound data to the core. And it needs to peel off the API actions and return them to the JS "application", maybe through an EventEmitter or something.

We don't have any Transit code in magic-wormhole.rs yet, so we're limited to text-message transfers, and custom applications (i.e. a different APPID) that are content with small store-and-forward payloads. I've started poking at the Dilation work that would enable bulk transfers, but I need to finish some of the Python-side code (backwards compatibility with the Transit-based clients) before I'm likely to make too much progress on the Rust equivalent. (I don't intend to implement Transit in magic-wormhole.rs, but of course it'll be a lot easier to get away with that once I've shipped a python version that includes Dilation).

Any thoughts on what the JS API ought to be? My instinct is to make it look like the python Deferred API, where you create a Wormhole object and call methods on it which return Promises. But maybe something that takes .on('message', cb) would be more idiomatic? Or, I guess we could do both?

from magic-wormhole.rs.

warner avatar warner commented on May 24, 2024

Ok the second problem will be solved by an upcoming release of curve25519-dalek that switches to use zeroize instead of clear_on_drop (which depends upon zeroize-1.0 being finalized, but that sounds like it may happen soon). So we can just wait for that release.

from magic-wormhole.rs.

warner avatar warner commented on May 24, 2024

@burdges pointed out that cargo features are additive, so if the glue code declares its own dependency upon clear_on_drop = { .. features = ["no_cc"] }, then that'll push the no_cc all the way down the dependency graph. With that trick (and a change to magic-wormhole.rs to replace rustc-serialize with hex), I'm able to get the glue code to compile.

from magic-wormhole.rs.

piegamesde avatar piegamesde commented on May 24, 2024

The sodiumoxide issue is resolved now, can anyone knowing and interested in WASM give this a second try?

from magic-wormhole.rs.

corbinu avatar corbinu commented on May 24, 2024

@piegamesde I would be happy to take a run at it. I have been thinking especially since I love magic-wormhole. I would be interesting to have a static site up that was a WASM version for my non-cli friends and family. Would you be interested in that being a direct part of the project or should I just test as a library and possibly build it separately?

from magic-wormhole.rs.

piegamesde avatar piegamesde commented on May 24, 2024

@corbinu Great! Yeah, we're all dreaming of this :)

Would you be interested in that being a direct part of the project or should I just test as a library and possibly build it separately?

Tough question. I suggest you to try to include Wormhole as a library first, and if this doesn't work, we'll can talk about integrating it into the repository.

from magic-wormhole.rs.

andipabst avatar andipabst commented on May 24, 2024

I wanted to poke around this a little since I'd really love to use magic wormhole on the go in a browser (since a browser is just ubiquitous these days). I don't have any problem with writing the JavaScript wrapper/interop, but I don't really have much Rust experience.

So I tried to include magic-wormhole as a library, as you suggested @piegamesde.

magic-wormhole = { git = "https://github.com/magic-wormhole/magic-wormhole.rs", tag = "0.2.0"}

But unfortunately I can't get it to build as wasm. I could get around missing C-libraries by adjusting the build target wasm32-unknown-emscripten or wasm32-wasi. But now I am stuck since some libraries (e.g. socket2 for websocket) just are not available for wasm. That of course makes sense, since the browser/javascript would handle the websocket connections as part of the IO wrapper around magic-wormhole.rs

I have created a minimal example repository based on the wasm-pack-template for reference.

Could you please point me in the right direction on how to include/build this for wasm as a library?

from magic-wormhole.rs.

piegamesde avatar piegamesde commented on May 24, 2024

@andipabst thanks for looking into this. First of all, please use some recent commit instead of a release. The last release has been a while ago (sorry about that).

As far as I can tell socket2 is not part of our WebSockets stack. (The latter may be problematic as well, but one issue at a time.) We use socket2 for finding a direct connection. For WASM, that feature must be hidden behind a cargo feature flag. (Feel free to just rip it out for now to get things working.) There are some transitive dependencies of socket2 too (namely, async-io because of async-std). I don't really know how to fix that one yet.

from magic-wormhole.rs.

piegamesde avatar piegamesde commented on May 24, 2024

@andipabst I see that you have some commits on your fork. Can you please take the changes that prepare the repository for WASM support (dependencies, feature flags, code gates) and PR them?

from magic-wormhole.rs.

andipabst avatar andipabst commented on May 24, 2024

Hi @piegamesde, I tried again for some time, but unfortunately I was not able to get it working completely. I have pushed my work in progress state in my fork and in a separate repository for the webapp.

Should you decide to have a look at it and get it working, I would be happy to assist with the web part! But my Rust skills are simply not enough to get that part running at the moment.

from magic-wormhole.rs.

piegamesde avatar piegamesde commented on May 24, 2024

I started copying some of your code over, please check out what I've done in the dev branch and let me know what you think.

Most notably, I try to go without a wasm feature and do everything based on target platform instead. Conversely, even when compiling against WebAssembly you have the choice how many features of the protocol you want to support. (In the current commit, this is just the core protocol, but in the end we want to support everything but the port forwarding feature.)

I'll go ahead and try to integrate your transit changes next. Note that I haven't compiled against wasm target yet so that part is entirely untested. I'll also have to figure out a story how to build everything in CI.

from magic-wormhole.rs.

andipabst avatar andipabst commented on May 24, 2024

I had a look and it looks really good! Basing it on the target platform is a good idea, since I really had some trouble with the feature flag.
FYI, wasm-pack is building the package against the target wasm32-unknown-unknown.

I think it should be possible to include a cargo build --target wasm32-unknown-unknown into the CI pipeline, shouldn`t it?

from magic-wormhole.rs.

piegamesde avatar piegamesde commented on May 24, 2024

Thanks! Actually I'm not that happy about all the cfg flags I simply spammed in the transit module, but it will have to do for now. I'm pretty certain that the current transit handshake does not work and needs to be adapted for WebSockets, but that shouldn't be too hard.

I think it should be possible to include a cargo build --target wasm32-unknown-unknown into the CI pipeline, shouldn`t it?

Yes, that's the plan

from magic-wormhole.rs.

piegamesde avatar piegamesde commented on May 24, 2024

I think the changes should now be ready for actually trying them out in a browser. Since I've never done any web development beyond most basic HTML+CSS, I fear I won't be able to help out much there.

As far as I understand, one of the next steps would be to provide a JavaScript interop API, because most websites are JS based. Let me know if I can help anything there

from magic-wormhole.rs.

andipabst avatar andipabst commented on May 24, 2024

Thanks for your changes! I implemented a basic wasm integration. I had to change some parts, since std::time::Instant::now() is not implemented for wasm, but it compiles and runs now until it reaches the handshake.

Then I run into an issue, as you predicted: The handshake via the websocket relay server fails since it opens a new websocket connection to the relay server which then gets a "welcome" response instead of the expected handshake messages.

from magic-wormhole.rs.

piegamesde avatar piegamesde commented on May 24, 2024

Actually, the handshake should work fine, even though I haven't really tested it yet. What you describes sound like you are trying to connect to the rendezvous server as relay. I'm not sure if the public relay server even has a WebSocket endpoint. You can use my test server though, it should be reachable as tcp://piegames.de:4001 and ws://piegames.de:4002

from magic-wormhole.rs.

andipabst avatar andipabst commented on May 24, 2024

Thanks for the hint, that was indeed the issue 🤦

I could use with your test server for developing on my machine, but for making a hosted version available I needed a secure websocket endpoint (wss://), so I had to dust off my old Hetzner server a bit and run my own relay server (behind a nginx proxy for letsencrypt ssl termination).

You can see the result here: https://magic-wormhole-wasm.netlify.app/
It is still very rough, but it's a proof of concept and it works 😄 🎉

So going forward, I will polish the code a bit more and then plan to separate the wasm package and my reference implementation of the web-app using it.

from magic-wormhole.rs.

piegamesde avatar piegamesde commented on May 24, 2024

Oh I forgot to add the TLS reverse proxy to the endpoint, hence no WSS. To be honest though, I'm not sure that using TLS provides any additional security given that the transit protocol is built to work with plain TCP connections too. But I'll see if I can add it anyways, shouldn't hurt either.

from magic-wormhole.rs.

andipabst avatar andipabst commented on May 24, 2024

Thanks!

As mentioned above I polished and documented the code a bit and copied it over to include it in this repo, see #163.
I also adapted the GitHub Actions files so the wasm-assets are built and packaged.

The next step would be to publish this artifact to the JavaScript package registry npm. See the wasm-pack documentation for more details on the technical process.

@piegamesde Can you do please do this, as you are a maintainer and also publishing the rust parts to crates.io?

Meanwhile, I would go on writing the JavaScript/TypeScript reference implementation I mentioned above.

from magic-wormhole.rs.

piegamesde avatar piegamesde commented on May 24, 2024

This is pretty cool, many thanks! However, I must admit that I have little knowledge about JavaScript and the npm ecosystem, so I wouldn't feel comfortable with pushing things there at the moment. Would you mind becoming the maintainer for the JavaScript bindings of wormhole-rs?

from magic-wormhole.rs.

Sky-NiniKo avatar Sky-NiniKo commented on May 24, 2024

Edit

I found the error and it was very simple. I am stupid. Look at #189 for the fix.

Original post

Hi, I'm a beginner in Rust and even more in Wasm but I tried to make a web application using yew and magic-wormhole.rs and I got this error while trying to upload a file. Logs from the console (F12 -> Console):

panicked at 'Error: getrandom: this target is not supported', /home/niels/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rand_core-0.5.1/src/os.rs:63:13

Stack:

getImports/imports.wbg.__wbg_new_abda76e883ba8a5f@http://127.0.0.1:8080/yew-app-21e2076cdb23f7ca.js:402:21
console_error_panic_hook::Error::new::h0d0fabec9486fdef@http://127.0.0.1:8080/yew-app-21e2076cdb23f7ca_bg.wasm:wasm-function[14162]:0x4f80b7
console_error_panic_hook::hook_impl::ha02f1ef761b122b6@http://127.0.0.1:8080/yew-app-21e2076cdb23f7ca_bg.wasm:wasm-function[2713]:0x34b3ba
console_error_panic_hook::hook::h77afd9ec18c650a2@http://127.0.0.1:8080/yew-app-21e2076cdb23f7ca_bg.wasm:wasm-function[16028]:0x511213
core::ops::function::Fn::call::ha887bd5a651c1c2d@http://127.0.0.1:8080/yew-app-21e2076cdb23f7ca_bg.wasm:wasm-function[13452]:0x4ed1a2
std::panicking::rust_panic_with_hook::ha2f7b95083ec77f3@http://127.0.0.1:8080/yew-app-21e2076cdb23f7ca_bg.wasm:wasm-function[5452]:0x40c00c
std::panicking::begin_panic_handler::{{closure}}::h47a7e7226e82fb78@http://127.0.0.1:8080/yew-app-21e2076cdb23f7ca_bg.wasm:wasm-function[6812]:0x449861
std::sys_common::backtrace::__rust_end_short_backtrace::h114c7ac12e473e06@http://127.0.0.1:8080/yew-app-21e2076cdb23f7ca_bg.wasm:wasm-function[18384]:0x525920
rust_begin_unwind@http://127.0.0.1:8080/yew-app-21e2076cdb23f7ca_bg.wasm:wasm-function[11258]:0x4c5140
core::panicking::panic_fmt::hae2225a32154cb21@http://127.0.0.1:8080/yew-app-21e2076cdb23f7ca_bg.wasm:wasm-function[15335]:0x5083f4
<rand_core::os::OsRng as rand_core::RngCore>::fill_bytes::he1c5c8da3ce8e69d@http://127.0.0.1:8080/yew-app-21e2076cdb23f7ca_bg.wasm:wasm-function[3098]:0x36edce
curve25519_dalek::scalar::Scalar::random::h3a482c24f807c76f@http://127.0.0.1:8080/yew-app-21e2076cdb23f7ca_bg.wasm:wasm-function[4271]:0x3c77d7
<spake2::ed25519::Ed25519Group as spake2::group::Group>::random_scalar::h5074f6af435f4cfa@http://127.0.0.1:8080/yew-app-21e2076cdb23f7ca_bg.wasm:wasm-function[15136]:0x5058bc
spake2::Spake2<G>::start_symmetric_with_rng::h9310dbd0fe484fee@http://127.0.0.1:8080/yew-app-21e2076cdb23f7ca_bg.wasm:wasm-function[3682]:0x39df73
spake2::Spake2<G>::start_symmetric::h4a14f98f0ef1f101@http://127.0.0.1:8080/yew
...

I think I understood that curve25519_dalek wants to generate a random number but it can't because rand_core doesn't support wasm32-unknown-unknown:

I also tried andipabst's code without much success. It doesn't produce the same Traceback but I think the problem is the same. (Edit: After testing the fix, I can say that it is another issue.) I think you don't have much control over this kind of problem, but who knows.

from magic-wormhole.rs.

Sky-NiniKo avatar Sky-NiniKo commented on May 24, 2024

So now that this is settled, I have a new problem. It is likely that this is a misunderstanding of your module on my part and maybe this is not the best place to ask if that is the case.

But, here is the problem: when handshaking with the peer, I get in the console ​`follower_connect` timed out almost instantly after Using secretbox for encryption and then a fatal error.

My code is available here if you want to try: https://github.com/Sky-NiniKo/magic-wormhole-yew

from magic-wormhole.rs.

piegamesde avatar piegamesde commented on May 24, 2024

Your code looks okay on a first glance. Can you get some better error messages or maybe even a stack trace?

from magic-wormhole.rs.

Sky-NiniKo avatar Sky-NiniKo commented on May 24, 2024

Full stack trace

DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Welcome { welcome: WelcomeMessage { current_cli_version: None, motd: None, error: None, permission_required: None } }
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:113 Sending Bind { appid: AppID("lothar.com/wormhole/text-or-file-xfer"), side: MySide(EitherSide("1d9dc6ef90")) }
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Ack
INFO magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:400 Connected to rendezvous server.
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:113 Sending List
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Ack
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Nameplates { nameplates: [Nameplate("1"), Nameplate("15"), Nameplate("2"), Nameplate("3"), Nameplate("4"), Nameplate("5"), Nameplate("56"), Nameplate("58"), Nameplate("6"), Nameplate("7"), Nameplate("77"), Nameplate("8"), Nameplate("80"), Nameplate("82"), Nameplate("9"), Nameplate("92")] }
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:113 Sending Claim { nameplate: "80" }
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Ack
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Claimed { mailbox: Mailbox("dqdhjrtrj3jr2") }
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:113 Sending Open { mailbox: Mailbox("dqdhjrtrj3jr2") }
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Ack
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core.rs:190 Connected to mailbox dqdhjrtrj3jr2
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:113 Sending Add { phase: Phase("pake"), body: [123, 34, 112, 97, 107, 101, 95, 118, 49, 34, 58, 34, 53, 51, 55, 54, 52, 99, 56, 98, 99, 101, 49, 51, 54, 99, 101, 51, 99, 99, 100, 48, 57, 101, 52, 102, 57, 97, 99, 54, 57, 55, 101, 49, 98, 55, 48, 48, 50, 97, 53, 54, 52, 49, 56, 51, 55, 52, 53, 52, 53, 97, 51, 52, 52, 100, 99, 100, 100, 99, 51, 57, 53, 53, 55, 53, 98, 101, 34, 125] }
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Message(EncryptedMessage { side: TheirSide(EitherSide("cb822f272a")), phase: Phase("pake"), body: [123, 34, 112, 97, 107, 101, 95, 118, 49, 34, 58, 34, 53, 51, 101, 55, 100, 54, 53, 98, 52, 48, 55, 48, 102, 102, 53, 50, 50, 97, 48, 53, 57, 52, 56, 57, 55, 48, 51, 54, 98, 55, 55, 49, 53, 50, 51, 98, 97, 98, 101, 51, 56, 100, 49, 100, 53, 48, 100, 48, 97, 55, 53, 97, 53, 48, 100, 97, 53, 52, 101, 48, 101, 55, 48, 51, 54, 98, 34, 125] })
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Ack
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:113 Sending Add { phase: Phase("version"), body: [175, 91, 198, 46, 155, 246, 57, 123, 231, 232, 5, 65, 106, 88, 250, 66, 76, 34, 144, 2, 213, 6, 16, 10, 1, 46, 0, 47, 32, 60, 98, 83, 189, 140, 62, 119, 243, 57, 16, 153, 186, 207, 167, 159, 241, 2, 207, 147, 233, 143, 9, 172, 99, 45, 193, 72, 126, 224, 33, 52, 138, 16, 190, 71, 95, 76, 49, 128, 234, 130, 142, 136, 80, 129] }
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Message(EncryptedMessage { side: TheirSide(EitherSide("1d9dc6ef90")), phase: Phase("pake"), body: [123, 34, 112, 97, 107, 101, 95, 118, 49, 34, 58, 34, 53, 51, 55, 54, 52, 99, 56, 98, 99, 101, 49, 51, 54, 99, 101, 51, 99, 99, 100, 48, 57, 101, 52, 102, 57, 97, 99, 54, 57, 55, 101, 49, 98, 55, 48, 48, 50, 97, 53, 54, 52, 49, 56, 51, 55, 52, 53, 52, 53, 97, 51, 52, 52, 100, 99, 100, 100, 99, 51, 57, 53, 53, 55, 53, 98, 101, 34, 125] })
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Message(EncryptedMessage { side: TheirSide(EitherSide("cb822f272a")), phase: Phase("version"), body: [85, 136, 167, 165, 93, 143, 208, 168, 142, 185, 147, 140, 62, 30, 204, 32, 116, 19, 106, 21, 79, 160, 74, 91, 206, 27, 170, 144, 235, 85, 97, 185, 145, 225, 179, 189, 172, 71, 61, 236, 131, 108, 132, 3, 176, 179, 58, 226, 178, 46, 201, 182, 170, 252, 140, 130, 172, 56, 160, 76, 71, 85, 142, 45, 255, 201, 78, 60, 213, 42, 138, 191, 93, 162] })
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Ack
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:113 Sending Release { nameplate: "80" }
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Message(EncryptedMessage { side: TheirSide(EitherSide("1d9dc6ef90")), phase: Phase("version"), body: [175, 91, 198, 46, 155, 246, 57, 123, 231, 232, 5, 65, 106, 88, 250, 66, 76, 34, 144, 2, 213, 6, 16, 10, 1, 46, 0, 47, 32, 60, 98, 83, 189, 140, 62, 119, 243, 57, 16, 153, 186, 207, 167, 159, 241, 2, 207, 147, 233, 143, 9, 172, 99, 45, 193, 72, 126, 224, 33, 52, 138, 16, 190, 71, 95, 76, 49, 128, 234, 130, 142, 136, 80, 129] })
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Ack
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Released
INFO magic-wormhole.rs-1dca7428e7ab11a3/src/core.rs:252 Found peer on the rendezvous server.
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/transfer.rs:352 Sending transit message 'Hints { direct_tcp: {}, relay: [RelayHint { name: None, tcp: {DirectHint { hostname: "transit.magic-wormhole.io", port: 4001 }}, ws: {} }] }
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:113 Sending Add { phase: Phase("0"), body: [128, 224, 186, 102, 222, 81, 100, 172, 56, 164, 174, 110, 109, 80, 201, 39, 102, 251, 112, 83, 158, 206, 141, 126, 119, 181, 252, 127, 18, 36, 36, 140, 7, 213, 90, 251, 206, 172, 116, 93, 174, 167, 79, 100, 54, 246, 55, 220, 116, 197, 230, 87, 69, 102, 9, 52, 178, 112, 134, 63, 22, 157, 183, 6, 188, 75, 176, 58, 168, 173, 118, 175, 134, 104, 96, 104, 12, 214, 113, 135, 54, 130, 252, 64, 246, 202, 87, 253, 101, 186, 51, 216, 26, 74, 197, 11, 215, 229, 79, 252, 132, 142, 52, 141, 13, 24, 242, 59, 105, 28, 221, 209, 19, 119, 28, 128, 211, 234, 162, 75, 55, 109, 168, 25, 230, 46, 40, 255, 51, 134, 7, 1, 10, 254, 136, 255, 163, 217, 228, 205, 78, 169, 144, 107, 253, 196, 79, 131, 138, 44, 77, 44, 243, 187, 14, 31, 7, 76, 99, 147, 80, 197, 8, 232, 2, 231, 140, 203, 225, 167, 180, 133, 253, 234, 217, 230, 148, 188, 8, 225, 213, 216, 129, 133, 82, 66, 124, 247, 98, 121, 60, 94, 52, 71, 252, 201, 250, 231, 21, 147, 64, 101, 137, 142, 78, 19, 223, 112, 81, 229, 28, 156, 190, 216, 192, 99, 141, 107, 117, 209, 117, 61, 165, 101, 250, 57, 196, 251, 113, 129, 182, 16, 35, 186, 209, 4, 132, 247, 252, 228, 130, 109, 44, 190, 20, 234] }
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Ack
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Message(EncryptedMessage { side: TheirSide(EitherSide("1d9dc6ef90")), phase: Phase("0"), body: [128, 224, 186, 102, 222, 81, 100, 172, 56, 164, 174, 110, 109, 80, 201, 39, 102, 251, 112, 83, 158, 206, 141, 126, 119, 181, 252, 127, 18, 36, 36, 140, 7, 213, 90, 251, 206, 172, 116, 93, 174, 167, 79, 100, 54, 246, 55, 220, 116, 197, 230, 87, 69, 102, 9, 52, 178, 112, 134, 63, 22, 157, 183, 6, 188, 75, 176, 58, 168, 173, 118, 175, 134, 104, 96, 104, 12, 214, 113, 135, 54, 130, 252, 64, 246, 202, 87, 253, 101, 186, 51, 216, 26, 74, 197, 11, 215, 229, 79, 252, 132, 142, 52, 141, 13, 24, 242, 59, 105, 28, 221, 209, 19, 119, 28, 128, 211, 234, 162, 75, 55, 109, 168, 25, 230, 46, 40, 255, 51, 134, 7, 1, 10, 254, 136, 255, 163, 217, 228, 205, 78, 169, 144, 107, 253, 196, 79, 131, 138, 44, 77, 44, 243, 187, 14, 31, 7, 76, 99, 147, 80, 197, 8, 232, 2, 231, 140, 203, 225, 167, 180, 133, 253, 234, 217, 230, 148, 188, 8, 225, 213, 216, 129, 133, 82, 66, 124, 247, 98, 121, 60, 94, 52, 71, 252, 201, 250, 231, 21, 147, 64, 101, 137, 142, 78, 19, 223, 112, 81, 229, 28, 156, 190, 216, 192, 99, 141, 107, 117, 209, 117, 61, 165, 101, 250, 57, 196, 251, 113, 129, 182, 16, 35, 186, 209, 4, 132, 247, 252, 228, 130, 109, 44, 190, 20, 234] })
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Message(EncryptedMessage { side: TheirSide(EitherSide("cb822f272a")), phase: Phase("0"), body: [177, 90, 215, 34, 155, 141, 113, 22, 196, 201, 225, 13, 236, 208, 149, 160, 49, 18, 252, 205, 76, 39, 53, 38, 61, 230, 249, 43, 59, 148, 236, 24, 105, 198, 78, 27, 19, 49, 98, 220, 54, 245, 12, 178, 129, 220, 211, 205, 10, 173, 154, 40, 157, 61, 232, 107, 11, 3, 16, 184, 15, 131, 232, 175, 25, 175, 79, 70, 253, 92, 15, 252, 34, 215, 62, 4, 168, 7, 160, 212, 179, 249, 33, 150, 158, 139, 221, 242, 189, 237, 132, 166, 176, 200, 23, 158, 155, 157, 198, 82, 217, 163, 75, 80, 101, 193, 128, 116, 104, 136, 18, 38, 227, 94, 26, 186, 5, 183, 252, 207, 212, 36, 74, 166, 133, 217, 109, 138, 145, 232, 255, 116, 223, 114, 201, 189, 237, 219, 112, 137, 95, 169, 0, 62, 96, 97, 167, 101, 122, 139, 106, 154, 239, 73, 9, 184, 187, 136, 48, 230, 99, 11, 213, 167, 186, 202, 217, 11, 182, 141, 180, 154, 92, 232, 83, 185, 255, 253, 152, 217, 143, 9, 18, 1, 4, 6, 182, 191, 133, 74, 77, 240, 106, 148, 93, 72, 102, 207, 167, 137, 245, 62, 104, 252, 197, 228, 97, 185, 111, 165, 1, 230, 40, 142, 103, 65, 156, 12, 47, 132, 74, 109, 7, 162, 65, 148, 215, 250, 15, 66, 34, 84, 226, 147, 188, 114, 153, 107, 26, 236, 150, 119, 132, 11, 226, 145, 143, 113, 237, 151, 25, 113, 207, 98, 125, 251, 125, 238, 179, 37, 155, 138, 188, 15, 93, 249, 93, 240, 174, 106, 201, 206, 140, 255, 78, 225, 60, 108, 59, 56, 11, 55, 33, 110, 105, 205, 159, 211, 226, 30, 47, 22, 205, 132, 177, 165, 52, 50, 32, 127, 71, 237, 51, 216, 85, 36, 188, 96, 224, 35, 217, 76, 85, 17, 131, 205, 171, 178, 17, 227, 9, 29, 73, 227, 147, 140, 174, 133, 106, 163, 228, 24, 37, 123, 91, 181, 130, 34, 135, 194, 200, 43, 237, 209, 97, 174, 93, 151, 100, 160, 22, 170, 213, 7, 121, 177, 11, 157, 193, 194, 246, 177, 207, 44, 140, 55, 147, 95, 154, 17, 29, 2, 210, 162, 85, 74, 78, 218, 204, 0, 114, 163, 173, 2, 4, 233, 39, 198, 2, 32, 28, 158, 61, 36, 181, 219, 233, 37, 172, 95, 69, 12, 73, 36, 53, 208, 140, 162, 52, 253, 119, 83, 142, 118, 131, 145, 139, 208, 82, 126, 244, 40, 229, 64, 101, 117, 52, 125, 251, 144, 255, 255, 33, 236, 114, 36, 65, 3, 71, 135, 56, 242, 87] })
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/transfer.rs:364 received transit message: TransitV1 { abilities_v1: Abilities { direct_tcp_v1: true, relay_v1: true, noise_v1: false }, hints_v1: Hints { direct_tcp: {DirectHint { hostname: "192.168.2.105", port: 40649 }, DirectHint { hostname: "175.158.176.244", port: 39241 }, DirectHint { hostname: "192.168.2.105", port: 39241 }}, relay: [RelayHint { name: None, tcp: {DirectHint { hostname: "transit.magic-wormhole.io", port: 4001 }}, ws: {} }] } }
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Message(EncryptedMessage { side: TheirSide(EitherSide("cb822f272a")), phase: Phase("1"), body: [72, 101, 30, 154, 176, 249, 247, 66, 126, 242, 213, 8, 152, 125, 56, 242, 178, 0, 127, 18, 124, 167, 154, 184, 2, 166, 127, 173, 49, 154, 85, 74, 87, 148, 46, 53, 14, 198, 140, 71, 92, 185, 250, 180, 43, 197, 8, 70, 213, 86, 21, 152, 47, 184, 69, 34, 32, 1, 38, 74, 227, 38, 129, 58, 24, 23, 202, 234, 98, 162, 216, 47, 11, 101, 17, 132, 173, 115, 109, 121, 117, 169, 211, 240, 72, 41, 55, 179, 123, 144, 227, 66, 163, 107, 211, 18, 185, 194, 190, 30, 216, 220, 105, 147, 151, 61, 137, 102, 109, 233, 95, 117, 215, 162, 113, 193, 30, 177, 244, 250, 116, 232, 19] })
INFO src/helpers.rs:137 File name: "Orbital Strike Fire Control.xlsx", size: 26847
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/transfer.rs:463 Sending ack
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:113 Sending Add { phase: Phase("1"), body: [217, 139, 79, 197, 16, 74, 128, 10, 73, 73, 167, 100, 110, 217, 164, 25, 135, 133, 205, 169, 22, 123, 97, 169, 15, 62, 181, 218, 158, 90, 174, 59, 174, 156, 34, 226, 20, 183, 15, 243, 197, 52, 16, 89, 172, 169, 251, 55, 174, 212, 60, 163, 223, 89, 240, 35, 56, 55, 68, 157, 184, 206, 228, 240, 143, 250, 134, 197] }
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Ack
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/transit.rs:1040 Using secretbox for encryption
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/transit.rs:999 `follower_connect` timed out
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/transfer.rs:587 Transfer encountered an error (Error while establishing transit connection), doing cleanup logic
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:113 Sending Add { phase: Phase("2"), body: [212, 83, 142, 73, 87, 35, 11, 4, 3, 29, 177, 106, 111, 83, 233, 156, 239, 107, 44, 56, 118, 49, 168, 35, 57, 16, 29, 4, 49, 180, 212, 128, 187, 167, 246, 148, 162, 6, 208, 117, 233, 180, 209, 209, 86, 186, 47, 115, 28, 71, 78, 242, 7, 54, 23, 55, 169, 159, 167, 37, 24, 245, 189, 178, 0, 213, 214, 171, 190, 120, 20, 235, 162, 163, 131, 81, 22, 244, 69, 228, 137, 54, 222, 89, 86, 34, 26, 170, 243, 230, 2, 237, 179, 117, 10] }
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Message(EncryptedMessage { side: TheirSide(EitherSide("1d9dc6ef90")), phase: Phase("1"), body: [217, 139, 79, 197, 16, 74, 128, 10, 73, 73, 167, 100, 110, 217, 164, 25, 135, 133, 205, 169, 22, 123, 97, 169, 15, 62, 181, 218, 158, 90, 174, 59, 174, 156, 34, 226, 20, 183, 15, 243, 197, 52, 16, 89, 172, 169, 251, 55, 174, 212, 60, 163, 223, 89, 240, 35, 56, 55, 68, 157, 184, 206, 228, 240, 143, 250, 134, 197] })
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Ack
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core.rs:340 Closing Wormhole…
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:113 Sending Close { mailbox: Mailbox("dqdhjrtrj3jr2"), mood: Happy }
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Message(EncryptedMessage { side: TheirSide(EitherSide("1d9dc6ef90")), phase: Phase("2"), body: [212, 83, 142, 73, 87, 35, 11, 4, 3, 29, 177, 106, 111, 83, 233, 156, 239, 107, 44, 56, 118, 49, 168, 35, 57, 16, 29, 4, 49, 180, 212, 128, 187, 167, 246, 148, 162, 6, 208, 117, 233, 180, 209, 209, 86, 186, 47, 115, 28, 71, 78, 242, 7, 54, 23, 55, 169, 159, 167, 37, 24, 245, 189, 178, 0, 213, 214, 171, 190, 120, 20, 235, 162, 163, 131, 81, 22, 244, 69, 228, 137, 54, 222, 89, 86, 34, 26, 170, 243, 230, 2, 237, 179, 117, 10] })
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Ack
DEBUG magic-wormhole.rs-1dca7428e7ab11a3/src/core/rendezvous.rs:250 Received Closed
ERROR src/helpers.rs:162 Error in data transfer: TransitConnect(Handshake)
imports.wbg.__wbg_error_fd84ca2a8a977774 @ yew-app-66c5cf24a68668b6.js:613
$web_sys::features::gen_console::console::error_4::hae9e29ffd50baa7e @ yew-app-66c5cf24a68668b6_bg.wasm:0x4c72a0
$<wasm_logger::WasmLogger as log::Log>::log::hc3ca7c0c3b15c046 @ yew-app-66c5cf24a68668b6_bg.wasm:0x1cbbf6
$log::__private_api_log::h65afdb4a78a773be @ yew-app-66c5cf24a68668b6_bg.wasm:0x318a1d
$yew_app::helpers::receive::{{closure}}::h2ad710554d94bccc @ yew-app-66c5cf24a68668b6_bg.wasm:0xd7d1d
$<yew_app::App as yew::html::component::Component>::update::{{closure}}::ha63b5425cf10389d @ yew-app-66c5cf24a68668b6_bg.wasm:0x329c90
$wasm_bindgen_futures::task::singlethread::Task::run::h8a788153d6b2b07c @ yew-app-66c5cf24a68668b6_bg.wasm:0x343f42
$wasm_bindgen_futures::queue::QueueState::run_all::h80f711b4146bd0a3 @ yew-app-66c5cf24a68668b6_bg.wasm:0x2f4e55
$wasm_bindgen_futures::queue::Queue::new::{{closure}}::h7a33b9f690c56bc7 @ yew-app-66c5cf24a68668b6_bg.wasm:0x4cf5c1
$<dyn core::ops::function::FnMut<(A,)>+Output = R as wasm_bindgen::closure::WasmClosure>::describe::invoke::h6dfcc50a2c6e86eb @ yew-app-66c5cf24a68668b6_bg.wasm:0x462cff
__wbg_adapter_38 @ yew-app-66c5cf24a68668b6.js:234
real @ yew-app-66c5cf24a68668b6.js:192
Promise.then (async)
imports.wbg.__wbg_then_ec5db6d509eb475f @ yew-app-66c5cf24a68668b6.js:814
$js_sys::Promise::then::ha8394b7fc01e5c2c @ yew-app-66c5cf24a68668b6_bg.wasm:0x4f3ad8
$wasm_bindgen_futures::queue::Queue::schedule_task::h5b4c358d0b3b1850 @ yew-app-66c5cf24a68668b6_bg.wasm:0x3a8be6
$wasm_bindgen_futures::queue::Queue::push_task::h11d1470149519d40 @ yew-app-66c5cf24a68668b6_bg.wasm:0x548f4b
$wasm_bindgen_futures::task::singlethread::Task::wake_by_ref::{{closure}}::h590d3b62a1fca925 @ yew-app-66c5cf24a68668b6_bg.wasm:0x522b90
$std::thread::local::LocalKey<T>::try_with::h3761e43e9c7306a6 @ yew-app-66c5cf24a68668b6_bg.wasm:0x3c406c
$std::thread::local::LocalKey<T>::with::hbde80691454f4c99 @ yew-app-66c5cf24a68668b6_bg.wasm:0x483bea
$wasm_bindgen_futures::task::singlethread::Task::wake_by_ref::h544504dad3040bc9 @ yew-app-66c5cf24a68668b6_bg.wasm:0x46989c
$wasm_bindgen_futures::task::singlethread::Task::into_raw_waker::raw_wake::h2a1357ff71e556a2 @ yew-app-66c5cf24a68668b6_bg.wasm:0x4f2fd5
$core::task::wake::Waker::wake::h1483161ed0c09719 @ yew-app-66c5cf24a68668b6_bg.wasm:0x50676c
$futures_core::task::__internal::atomic_waker::AtomicWaker::wake::h83fb514b715889a1 @ yew-app-66c5cf24a68668b6_bg.wasm:0x3c72c1
$futures_channel::mpsc::UnboundedSenderInner<T>::queue_push_and_signal::h7d57643369107915 @ yew-app-66c5cf24a68668b6_bg.wasm:0x45daf3
$futures_channel::mpsc::UnboundedSender<T>::do_send_nb::h7daf7c9178d7d20c @ yew-app-66c5cf24a68668b6_bg.wasm:0x2eca3e
$futures_channel::mpsc::UnboundedSender<T>::start_send::hc225ca4bc18114b6 @ yew-app-66c5cf24a68668b6_bg.wasm:0x469633
$futures_channel::mpsc::sink_impl::<impl futures_sink::Sink<T> for futures_channel::mpsc::UnboundedSender<T>>::start_send::h5a43c94b69c06fb2 @ yew-app-66c5cf24a68668b6_bg.wasm:0x45fec6
$<pharos::events::Sender<Event> as futures_sink::Sink<Event>>::start_send::h35841625c57eb708 @ yew-app-66c5cf24a68668b6_bg.wasm:0x371dc5
$<pharos::pharos::Pharos<Event> as futures_sink::Sink<Event>>::start_send::hb2ca4264a3476ebe @ yew-app-66c5cf24a68668b6_bg.wasm:0x23e07b
$<&mut S as futures_sink::Sink<Item>>::start_send::h57517aaff4d1cb37 @ yew-app-66c5cf24a68668b6_bg.wasm:0x43339c
$<futures_util::sink::feed::Feed<Si,Item> as core::future::future::Future>::poll::h2cf6c15389ea45a2 @ yew-app-66c5cf24a68668b6_bg.wasm:0x2084c9
$<futures_util::sink::send::Send<Si,Item> as core::future::future::Future>::poll::hf03a59d1413e0b47 @ yew-app-66c5cf24a68668b6_bg.wasm:0x20e11b
$pharos::shared_pharos::SharedPharos<Event>::notify::{{closure}}::h889e76c75daffd30 @ yew-app-66c5cf24a68668b6_bg.wasm:0x207f64
$ws_stream_wasm::notify::{{closure}}::he5d0b8faa6e43479 @ yew-app-66c5cf24a68668b6_bg.wasm:0x2438ab
$wasm_bindgen_futures::task::singlethread::Task::run::h8a788153d6b2b07c @ yew-app-66c5cf24a68668b6_bg.wasm:0x343f42
$wasm_bindgen_futures::queue::QueueState::run_all::h80f711b4146bd0a3 @ yew-app-66c5cf24a68668b6_bg.wasm:0x2f4e55
$wasm_bindgen_futures::queue::Queue::new::{{closure}}::h7a33b9f690c56bc7 @ yew-app-66c5cf24a68668b6_bg.wasm:0x4cf5c1
$<dyn core::ops::function::FnMut<(A,)>+Output = R as wasm_bindgen::closure::WasmClosure>::describe::invoke::h6dfcc50a2c6e86eb @ yew-app-66c5cf24a68668b6_bg.wasm:0x462cff
__wbg_adapter_38 @ yew-app-66c5cf24a68668b6.js:234
real @ yew-app-66c5cf24a68668b6.js:192
Promise.then (async)
imports.wbg.__wbg_then_ec5db6d509eb475f @ yew-app-66c5cf24a68668b6.js:814
$js_sys::Promise::then::ha8394b7fc01e5c2c @ yew-app-66c5cf24a68668b6_bg.wasm:0x4f3ad8
$wasm_bindgen_futures::queue::Queue::schedule_task::h5b4c358d0b3b1850 @ yew-app-66c5cf24a68668b6_bg.wasm:0x3a8be6
$wasm_bindgen_futures::task::singlethread::Task::spawn::{{closure}}::hea9ba258c114702b @ yew-app-66c5cf24a68668b6_bg.wasm:0x548f88
$std::thread::local::LocalKey<T>::try_with::hc5a2acde844cf758 @ yew-app-66c5cf24a68668b6_bg.wasm:0x3ba291
$std::thread::local::LocalKey<T>::with::h77993236e69f32cb @ yew-app-66c5cf24a68668b6_bg.wasm:0x483b2e
$wasm_bindgen_futures::task::singlethread::Task::spawn::h00ae90f61bcbf36c @ yew-app-66c5cf24a68668b6_bg.wasm:0x2efb57
$wasm_bindgen_futures::spawn_local::hf15163bb96a9814d @ yew-app-66c5cf24a68668b6_bg.wasm:0x4c3302
$ws_stream_wasm::notify::h056220f91729e0e0 @ yew-app-66c5cf24a68668b6_bg.wasm:0x421043
$ws_stream_wasm::ws_meta::WsMeta::connect::{{closure}}::{{closure}}::h62d739f2977772c5 @ yew-app-66c5cf24a68668b6_bg.wasm:0x3439a8
$<dyn core::ops::function::FnMut<(A,)>+Output = R as wasm_bindgen::closure::WasmClosure>::describe::invoke::hc1ad189d7c98d7a2 @ yew-app-66c5cf24a68668b6_bg.wasm:0x461841
__wbg_adapter_32 @ yew-app-66c5cf24a68668b6.js:226
real @ yew-app-66c5cf24a68668b6.js:192

Video demo

Final.webm

from magic-wormhole.rs.

piegamesde avatar piegamesde commented on May 24, 2024

Ah well, that's easy: the default relay server deployment does not have WebSocket transport enabled yet, however that's the only thing web clients support. So you need to host your own relay, and configure the client correctly.

from magic-wormhole.rs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.