The room id was read from the query string with a hand-rolled parser that
never decoded it, while the id was written back into the URL without any
encoding:
getFromURL = (key, search) =>
search.slice(1).split('&')
.find((param) => param.startsWith(`${key}=`))?.split('=')[1];
window.history.pushState({roomId: id}, '', id ? `?room=${id}` : '?');
Browsers percent-encode non-ASCII characters when a URL is serialized, so a
room named "不辞" is shared as `?room=%E4%B8%8D%E8%BE%9E`, but the client then
joins the literal `%E4%B8%8D%E8%BE%9E` room, which does not exist:
-> {"type":"join","payload":{"id":"%E4%B8%8D%E8%BE%9E"}}
<- close 1000 "room with id %E4%B8%8D%E8%BE%9E does not exist"
The same asymmetry also broke ids containing `&`, `=`, `+`, `#` or `%`, and
made ids that already contain percent escapes gain another encoding level on
every write, producing broken (double encoded) share links.
Use the platform URL API, which decodes on read and encodes on write exactly
once:
new URLSearchParams(search).get(key) ?? undefined
const params = new URLSearchParams();
params.set('room', id);
window.history.pushState({roomId: id}, '', `?${params.toString()}`);
No server change is needed: the room id stays the raw, human-readable string
that the ws `create`/`join` payload and the server-side room map already use,
and existing share links keep working.
Verified: URL round-trip for 不辞 / "my room" / "a+b" / "a&b=c" / "100%",
protocol-level e2e against a live server (encoded id -> "does not exist",
decoded id -> joins, cleanup on owner leave), `yarn build` (tsc + vite) and
`prettier --check src/useRoomID.ts`.
Both connectionstatechange handlers treated 'disconnected' the same as
'closed' and 'failed' and immediately called peer.close().
Per the WebRTC spec, 'disconnected' only means that ICE connectivity checks
are currently failing. The connection frequently recovers on its own -- brief
network hiccups, Wi-Fi roaming between access points, or NAT rebinding all
trigger it. Calling close() makes that recovery impossible, because a closed
RTCPeerConnection cannot be reopened.
The result was that a short network glitch permanently killed the stream and
the viewer had to reload the page. Leaving 'disconnected' unhandled lets the
browser's own ICE recovery do its job.
Refs #53
In client.go
if room, ok := message.(outgoing.Room); ok {
c.info.RoomID = room.ID
}
this part isn't thread safe. It could happen that user disconnected but
wasn't removed from a room, because the disconnecting go routine
couldn't see the roomID yet.
Deny/ban peers within specific CIDRs to prevent TURN server users from
accessing machines reachable by the TURN server but not from the
internet, useful when the server is behind a NAT.
By default denies local addresses.
ghcr.io's api doesn't let you see the pull count so I created [ghcr-pulls](https://github.com/ipitio/ghcr-pulls), a daily scraper that updates the count and makes this badge possible. I noticed that you use ghcr and have a docker hub counter and thought you might find this useful.