yjs / y-webrtc

WebRTC Connector for Yjs
MIT License
448 stars 109 forks source link

Problem with firefox and y-webrtc #56

Open dmkk3r opened 11 months ago

dmkk3r commented 11 months ago

Describe the bug I am currently building a collab whiteboard using SyncedStore (wrapper for yjs) and Sveltekit. So far everything works normally in Chrome. I use the y-webrtc provider for the SyncedStore and the connection is established successfully. However, if I use Firefox initially, no connection to the room is established. If I use a Chrome in parallel (Firefox next door still open in the non-synced tab) and establish the connection, Firefox also establishes the connection in parallel and synchronizes the document. I have attached a video below, which shows the exact procedure.

Expected behavior Firefox connects to the y-webrtc provider just like Chrome when you open the page and synchronizes the document.

Environment Information

Additional context

import { syncedStore, getYjsDoc } from '@syncedstore/core';
import { svelteSyncedStore } from '@syncedstore/svelte';
import { env } from '$env/dynamic/public';
import type { RetroBoard } from '$lib/types';
import { WebrtcProvider } from 'y-webrtc';

export const store = syncedStore({
    board: {} as RetroBoard
});
export const svelteStore = svelteSyncedStore(store);

const doc = getYjsDoc(store);

const provider = new WebrtcProvider('retrorealm-room', doc, {
    signaling: [env.PUBLIC_SIGNALING_SERVER],
    filterBcConns: false
});

export const awareness = provider.awareness;

https://github.com/yjs/y-webrtc/assets/26124256/ecccd10f-2eab-4153-83dc-feaceb02586a

ikezedev commented 11 months ago

I am experiencing similar behaviour, firefox is not able to sync and if you turn on the y-webrtc logs, you'd see that it just log infinitely

jeffrafter commented 11 months ago

I don't have a fix for this but I think that the source of the error is that Firefox WebRTC peers don't deliver ArrayBuffer data by default. They deliver blobs. Thus new UInt8Array(data) has a length of 0 and it fails. In the onmessage handler we'll need something like:

      // https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel/binaryType
      const buffer = peer.channel.binaryType === "arraybuffer" ? event.data : await event.data.arrayBuffer()
ikezedev commented 10 months ago

@jeffrafter where is this onmessage handler, I can't find it in src/y-webrtc.js or you meant this?

jeffrafter commented 10 months ago

@ikezedev ah, sorry I was referencing the buffered fork from @disarticulate. In the default y-webrtc the starting point is https://github.com/yjs/y-webrtc/blob/0cb5412e09e5d0c413ef72d87d8393093590cc06/src/y-webrtc.js#L233 (which is passed into readPeerMessage and then readMessage as you pointed out). The type hints in the signature claim that a UInt8Array is expected but it is a blob. (There is another spot in the broadcast channel handling and I am not sure if that is another spot where this happens). I think the fix in the default would be to put this into the peer handler, convert the data and then pass the appropriate buffer into readPeerMessage.