diff options
-rw-r--r-- | client-web/source/helper.ts | 1 | ||||
-rw-r--r-- | client-web/source/index.ts | 10 | ||||
-rw-r--r-- | client-web/source/preferences/decl.ts | 1 | ||||
-rw-r--r-- | client-web/source/user/mod.ts | 6 | ||||
-rw-r--r-- | client-web/source/user/remote.ts | 44 |
5 files changed, 58 insertions, 4 deletions
diff --git a/client-web/source/helper.ts b/client-web/source/helper.ts index a319172..e07fc7a 100644 --- a/client-web/source/helper.ts +++ b/client-web/source/helper.ts @@ -35,6 +35,7 @@ export const eh3 = elem_with_content("h3") export const eh4 = elem_with_content("h4") export const eh5 = elem_with_content("h5") export const eh6 = elem_with_content("h6") +export const epre = elem_with_content("pre") export const ediv = elem_with_children("div") export const etr = elem_with_children("tr") export const etd = elem_with_children("td") diff --git a/client-web/source/index.ts b/client-web/source/index.ts index 159bcce..baabdb4 100644 --- a/client-web/source/index.ts +++ b/client-web/source/index.ts @@ -13,8 +13,14 @@ export const ROOM_CONTAINER = ediv({ class: "room" }) export const RTC_CONFIG: RTCConfiguration = { iceServers: [ - { urls: ["stun:meet.metamuffin.org:16900"] }, - { urls: ["stun:stun1.l.google.com:19302", "stun:stun2.l.google.com:19302"] } // google stun!? + { + urls: [ + "turn:meet.metamuffin.org:16900", + "stun:meet.metamuffin.org:16900" + ], + username: "keksmeet", + credential: "ujCmetg6bm0" + }, ], iceCandidatePoolSize: 10, } diff --git a/client-web/source/preferences/decl.ts b/client-web/source/preferences/decl.ts index d641915..c0cf55d 100644 --- a/client-web/source/preferences/decl.ts +++ b/client-web/source/preferences/decl.ts @@ -13,6 +13,7 @@ export const PREF_DECLS = { username: { type: string, default: "guest-" + hex_id(), description: "Username", allow_url: true }, warn_redirect: { type: bool, hidden: true, default: false, description: "Internal option that is set by a server redirect.", allow_url: true }, image_view_popup: { type: bool, default: true, description: "Open image in popup instead of new tab" }, + webrtc_debug: { type: bool, default: false, description: "Show additional information for WebRTC related stuff" }, /* MEDIA */ microphone_enabled: { type: bool, default: false, description: "Add one microphone track on startup" }, diff --git a/client-web/source/user/mod.ts b/client-web/source/user/mod.ts index e2db9e9..581ac7e 100644 --- a/client-web/source/user/mod.ts +++ b/client-web/source/user/mod.ts @@ -1,5 +1,6 @@ /// <reference lib="dom" /> +import { epre, espan } from "../helper.ts"; import { ROOM_CONTAINER } from "../index.ts"; import { log } from "../logger.ts" import { Room } from "../room.ts" @@ -11,7 +12,8 @@ export abstract class User { public local = false public tracks: Set<TrackHandle> = new Set() - private name_el = document.createElement("span") + private name_el = espan("") + protected stats_el = epre("", { class: "stats" }) private _name?: string get name() { return this._name } set name(n: string | undefined) { this._name = n; this.name_el.textContent = this.display_name } @@ -49,7 +51,7 @@ export abstract class User { info_el.classList.add("info") this.name_el.textContent = this.display_name this.name_el.classList.add("name") - info_el.append(this.name_el) + info_el.append(this.name_el, this.stats_el) this.el.append(info_el) } diff --git a/client-web/source/user/remote.ts b/client-web/source/user/remote.ts index 243279b..07d8cf5 100644 --- a/client-web/source/user/remote.ts +++ b/client-web/source/user/remote.ts @@ -21,16 +21,19 @@ export class RemoteUser extends User { this.peer = new RTCPeerConnection(RTC_CONFIG) this.peer.onicecandidate = ev => { if (!ev.candidate) return + this.update_stats() log("webrtc", `ICE candidate set`, ev.candidate) room.signaling.send_relay({ ice_candidate: ev.candidate.toJSON() }, this.id) } this.peer.ontrack = ev => { const t = ev.track + this.update_stats() log("media", `remote track: ${this.display_name}`, t) this.add_track(new TrackHandle(t)) } this.peer.onnegotiationneeded = async () => { log("webrtc", `negotiation needed: ${this.display_name}`) + this.update_stats() while (this.negotiation_busy) { await new Promise<void>(r => setTimeout(() => r(), 100)) } @@ -38,7 +41,21 @@ export class RemoteUser extends User { } this.peer.onicecandidateerror = () => { log({ scope: "webrtc", warn: true }, "ICE error") + this.update_stats() } + this.peer.oniceconnectionstatechange = () => { + this.update_stats() + } + this.peer.onicegatheringstatechange = () => { + this.update_stats() + } + this.peer.onsignalingstatechange = () => { + this.update_stats() + } + this.peer.onconnectionstatechange = () => { + this.update_stats() + } + this.update_stats() } leave() { log("usermodel", `remove remote user: ${this.display_name}`) @@ -60,6 +77,32 @@ export class RemoteUser extends User { } } + async update_stats() { + if (!PREFS.webrtc_debug) return + try { + const stats = await this.peer.getStats() + let stuff = ""; + stuff += `ice-conn=${this.peer.iceConnectionState}; ice-gathering=${this.peer.iceGatheringState}; signaling=${this.peer.signalingState}\n` + stats.forEach(s => { + console.log("stat", s); + if (s.type == "candidate-pair" && s.selected) { + //@ts-ignore spec is weird.... + if (!stats.get) return + //@ts-ignore spec is weird.... + const cpstat = stats.get(s.localCandidateId) + if (!cpstat) return + console.log("cp", cpstat); + stuff += `via ${cpstat.candidateType}:${cpstat.protocol}:${cpstat.address}\n` + } else if (s.type == "codec") { + stuff += `using ${s.codecType ?? "dec/enc"}:${s.mimeType}(${s.sdpFmtpLine})\n` + } + }) + this.stats_el.textContent = stuff + } catch (e) { + console.warn(e); + } + } + async offer() { this.negotiation_busy = true const offer_description = await this.peer.createOffer() @@ -92,5 +135,6 @@ export class RemoteUser extends User { add_ice_candidate(candidate: RTCIceCandidateInit) { this.peer.addIceCandidate(new RTCIceCandidate(candidate)) + this.update_stats() } }
\ No newline at end of file |