munshkr / flok

Web-based P2P collaborative editor for live coding sounds and images
https://flok.cc
GNU General Public License v3.0
253 stars 38 forks source link

Web client joins session but gets empty editor buffer #102

Closed jwaldmann closed 2 years ago

jwaldmann commented 3 years ago

I am running a session with repl (-n tidal -- safe-tidal-cli) connected. The session has one web client. When another client joins (with a different IP address), it sees an empty buffer, but commands do get sent to the repl. Behaviour is not completely reproducible (client from the same IP address does see the buffer?)

Similar when closing the last web client, and then re-joining. Buffer visibility depends on address?

If it matters: I am running flok-web behind nginx reverse proxy.

http {
 server {
     listen       443 ssl;
...
          location / {
        proxy_pass "http://localhost:3000";
        proxy_set_header Host $host;
         proxy_set_header Upgrade $http_upgrade;
         proxy_set_header Connection 'upgrade';
         proxy_cache_bypass $http_upgrade;
       # proxy_set_header X-Real-IP $remote_addr;
     }
munshkr commented 3 years ago

Seems like you aren't seeing each other. Flok tries to use WebRTC first, then WebSockets, to sync changes. Maybe neither are working on your setup. This happened quite often when I was using only WebRTC, but I've seen WebSockets fixed those cases.

Right now Flok is using an external signaling server, maybe it went down or you can't access it from your network (it's wss://demos.yjs.dev right now). See https://github.com/munshkr/flok/blob/d7ba42ba32946061b0715f27685da8174d717f9c/packages/web/lib/SessionClient.ts#L92 Flok should set up its own signaling server actually, but haven't landed that yet. You can try to change it to another one and see if that fixes the problem on your end. Any signaling server should do.

munshkr commented 3 years ago

REPL works because that uses a custom Websocket server, not Yjs backends.

jwaldmann commented 3 years ago

Interesting! Yes, quite possibly my firewall blocks things.

Would that explain that it works between two clients from the same IP?

Can I avoid WebRTC/the signalling server altogether? Then it should work with websockets, regardless of IP?

I am a bit cautious about data privacy - for myself, and for my students. I am teaching at a state university, so I want to set a good example - and I have to, at least in my reading of the law. Although, maybe, that ship has long sailed, with all the rogue vidoeconferencing ...

munshkr commented 3 years ago

Can I avoid WebRTC/the signalling server altogether?

Let me check how it is setup, actually there might be something wrong there. In theory, the WebRTC falls back to WebSockets if it fails, so it should've worked...

I am a bit cautious about data privacy - for myself, and for my students. I am teaching at a state university, so I want to set a good example - and I have to, at least in my reading of the law. Although, maybe, that ship has long sailed, with all the rogue vidoeconferencing ...

That's perfectly reasonable, and you are setting a good example! We should make the effort to keep it that way :) One of my main goals from the start was to have an accessible but also a self-hosted application, and be mindful of the security issues involved, as much as possible (still trying to reach/keep it...)

jwaldmann commented 3 years ago

Good! - I don't know these technologies too well - how could I learn about the communication that is supposed to happen (between flok clients, flok server, possibly external server) when using the various methods?

For reference - we use BBB for lectures but I have to admit that I am not completely sure of its inner workings (e.g., TURN - "to bypass firewalls" - sounds scary). I hoped that flok is simpler - it sends only text. Well, at least in the configuration that I use. I am aware that it can do more.

munshkr commented 3 years ago

Unfortunately, I also had to read a bit about TURN and STUN servers, they are really needed for WebRTC to work :( I had to set up a TURN and STUN server on flok.clic.cf myself, and even then, there were some users that still had issues seeing each other. I found out later that it covers most cases but is not infallible. So, I went back to Websockets as a fallback.

You can check the Yjs README, it explains a bit about the algorithm it uses (CRDT), and how to combine different backends. I might have made a mistake somewhere, or maybe an Yjs bug too.

I think the relevant code in Flok is in the lib/SessionClient.ts if you want to try something (maybe as you said, disabling the WebRTC provider and using only WebSockets might work).

jwaldmann commented 3 years ago

[EDIT] my uMatrix had blocked yjs.dev. Aha! now I am getting some communication. Sorry for the noise.

I am confused now. Is it like this:

And then what I observe here is that communication between web clients only works if they are in two tabs within one browser - because there's some fallback somewhere that does avoid the external WS server altogether - in just that case?

munshkr commented 3 years ago

About uMatrix: Nice! Good to know, I should prioritize changing that yjs server (it was meant to be temporary). flok-web should fire up its own websockets server for that...

  1. WebRTC can use TURN and STUN servers to help connect peers between themselves, especially when they are behind proxies or NATs (this last one is really common with home internet connections). The details about the protocols, I don't remember right now, but basically their goal is to help peers know each other (their IPs) and communicate with each other directly.
  2. Flok is currently using two WebSockets servers: 1) The one you saw from yjs.dev, this is used for the code editors sync by Yjs. and 2) an internal WebSockets server created by flok-repl. flok-web acts as a client both for yjs.dev and flok-repl servers.
munshkr commented 3 years ago

And then what I observe here is that communication between web clients only works if they are in two tabs within one browser - because there's some fallback somewhere that does avoid the external WS server altogether - in just that case?

Yes :) WebRTC handles that automatically. It first tries to resolve it on LAN, then goes outside.

Maybe this helps (I should probably re-read everything and check it is working all right): https://bloggeek.me/webrtc-turn/