monitor-free.openapps.xyz

Source

This app’s code and revision history are public. Download a copy or explore the files below.

Public
The app’s code and revision history are public.
Owned app · rev 11d38ef641b0
Run it yourself
Take the whole tree and run it on your own machine. The download needs no account. Cloning needs a sign-in.
Download .zip
bounded clone 9383f719c9b37ff76411858f
A copy you download is not bounded. The guarantees this app runs under - declared egress, proven invariants, writes that fail closed - live in the runtime serving this page, not in the files. What you get is auditable source you can read and run, with no runtime guarantees attached.
← All files
src/lib/rtc.ts
// WebRTC pieces shared by the baby station and parent devices.

/**
 * How devices find a path to each other. Public STUN servers tell each device its address as the
 * internet sees it, which is enough on most home networks. Some networks (strict NAT, many mobile
 * carriers, office Wi-Fi) need a relay (TURN) instead; a relay carries the video itself and costs
 * money per gigabyte, so Monitor has none yet. To add one, return its address and short-lived
 * credentials here (fetched from a function, charged at cost); nothing else needs to change.
 */
export async function iceConfig(): Promise<RTCConfiguration> {
  return {
    iceServers: [{ urls: ["stun:stun.l.google.com:19302", "stun:stun.cloudflare.com:3478"] }],
  };
}

/**
 * Waits until the browser has found its network addresses (or 2.5 seconds pass), so one offer or
 * answer carries every address and the devices need only two signaling writes per connection.
 */
export function gathered(pc: RTCPeerConnection, maxMs = 2500): Promise<void> {
  if (pc.iceGatheringState === "complete") return Promise.resolve();
  return new Promise((resolve) => {
    const done = () => {
      pc.removeEventListener("icegatheringstatechange", check);
      clearTimeout(timer);
      resolve();
    };
    const check = () => { if (pc.iceGatheringState === "complete") done(); };
    const timer = setTimeout(done, maxMs);
    pc.addEventListener("icegatheringstatechange", check);
  });
}

const ALPHABET = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789";
/** A random id from an unambiguous alphabet; 20 characters is about 116 bits. */
export function randomId(length = 20): string {
  const bytes = crypto.getRandomValues(new Uint8Array(length));
  let out = "";
  for (const b of bytes) out += ALPHABET[b % ALPHABET.length];
  return out;
}

/** A 6-digit pairing code, never starting with 0 so it reads well. */
export function randomCode(): string {
  const n = crypto.getRandomValues(new Uint32Array(1))[0] % 900000;
  return String(100000 + n);
}

export type Quality = "good" | "fair" | "weak";
export type Route = "local" | "internet" | "relay";
export interface LinkStats { quality: Quality; route: Route | null }

/** Reads round-trip time, packet loss and the kind of path from a connection's stats. */
export class StatsReader {
  private lastLost = 0;
  private lastReceived = 0;

  async read(pc: RTCPeerConnection): Promise<LinkStats> {
    const report = await pc.getStats();
    let pair: any = null;
    let lost = 0;
    let received = 0;
    report.forEach((s: any) => {
      if (s.type === "transport" && s.selectedCandidatePairId) pair = report.get(s.selectedCandidatePairId) || pair;
      if (s.type === "inbound-rtp") { lost += s.packetsLost || 0; received += s.packetsReceived || 0; }
    });
    if (!pair) report.forEach((s: any) => { if (s.type === "candidate-pair" && s.nominated && s.state === "succeeded") pair = s; });
    const local = pair ? report.get(pair.localCandidateId) : null;
    const remote = pair ? report.get(pair.remoteCandidateId) : null;
    const types = [local?.candidateType, remote?.candidateType];
    const route: Route | null = !pair ? null : types.includes("relay") ? "relay" : types.every((t) => t === "host") ? "local" : "internet";
    const rtt = (pair?.currentRoundTripTime ?? 0) * 1000;
    const dLost = Math.max(0, lost - this.lastLost);
    const dReceived = Math.max(0, received - this.lastReceived);
    this.lastLost = lost;
    this.lastReceived = received;
    const loss = dLost + dReceived ? dLost / (dLost + dReceived) : 0;
    const quality: Quality = rtt < 250 && loss < 0.02 ? "good" : rtt < 600 && loss < 0.08 ? "fair" : "weak";
    return { quality, route };
  }
}

Change history

Move store links to openapps.free
11d38ef641 · 17 hours ago
Release with preview
41c8af3ee5 · 19 hours ago
Bind agent address in policy
5b2d792529 · 19 hours ago
Use OpenApps service URLs and add contribution strip (retry)
be4477dcb3 · 19 hours ago
Bounded source sync
5c9ec00c29 · 2 days ago
Bounded source sync
b33aa231f4 · 2 days ago
Bounded source sync
6cb67b3c8e · 2 days ago
Bounded source sync
e054acaa29 · 2 days ago