@robota-sdk/agent-transport-webrtc 3.0.0-beta.99 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- import{createRequire as e}from"node:module";import{HISTORY_PAGE_MAX_BYTES as t,createOutboundDelivery as n,createSessionMessageHandler as r}from"@robota-sdk/agent-transport";import{resolveAdmission as i}from"@robota-sdk/agent-transport/node";import{RENDEZVOUS_EPOCH_MS as a,decodeDeviceRevocationList as o,decodeDeviceRoster as s,decodeEnrollFrame as c,decodePairingFrame as l,decodeReconnectFrame as u,decodeSigningKeyRevocation as d,deriveIdentityId as f,derivePairRendezvous as ee,extractDtlsFingerprint as p,extractDtlsFingerprintAttribute as m,importPublicKey as te,rendezvousEpoch as h,startDeviceHandshake as ne,startHostReconnect as re,startPairingHandshake as ie,verifyDeviceChain as ae}from"@robota-sdk/agent-remote-pairing";import g,{WebSocketServer as oe}from"ws";import{ConnectionAuthority as se}from"@robota-sdk/agent-interface-session-mobility";import{createHash as _,createHmac as v,createPublicKey as ce,randomBytes as le,randomInt as ue,timingSafeEqual as y,verify as de}from"node:crypto";import{createSocket as fe}from"node:dgram";import{isIPv4 as b,isIPv6 as pe}from"node:net";import{networkInterfaces as x}from"node:os";import{SimplePool as me}from"nostr-tools/pool";import{finalizeEvent as he,getPublicKey as ge,verifyEvent as _e}from"nostr-tools/pure";function ve(e,t){return n(t=>e.send(JSON.stringify(t)),(e,n)=>t(e,n),()=>e.bufferedAmount)}const ye=/^[0-9A-F]{2}(?::[0-9A-F]{2})+$/;function S(e,t,n,r){let i=!1,a=()=>{if(i)return;i=!0;let a=e.remoteFingerprint();if(a===void 0){r(`the DTLS layer exposed no remote certificate`);return}let o=a.value.toUpperCase();if(a.algorithm.toLowerCase()!==t.toLowerCase()){r(`the remote certificate was checked with ${a.algorithm}, not ${t}`);return}if(!ye.test(o)){r(`the remote certificate fingerprint is malformed`);return}n(o)},o=e=>{i||(i=!0,r(`the connection ended ${e} before DTLS completed`))};if(e.state===`connected`)return a(),()=>void 0;if(e.state===`failed`||e.state===`closed`)return o(e.state),()=>void 0;let s=e.onStateChange(e=>{if(e===`connected`)a();else if(e===`failed`||e===`closed`)o(e);else return;s()});return s}const be=t=>e(import.meta.url)(t);function xe(e=be){try{let t=e(`node-datachannel`);if(typeof t?.PeerConnection!=`function`)throw Error(`no PeerConnection export`);return t}catch{throw Error(`WebRTC transport unavailable — the optional dependency "node-datachannel" is not installed or has no prebuilt binary for this platform (${process.platform}-${process.arch}).`)}}function C(e){try{return e?.()}catch{return}}function Se(e){return e instanceof Error?e.message:String(e)}const Ce={stun:3478,turn:3478,turns:5349};function we(e){let t=/^(stuns?|turns?):([^:?]+|\[[^\]]+\])(?::(\d{1,5}))?(?:\?transport=(udp|tcp))?$/i.exec(e.urls);if(!t)throw Error(`unsupported ICE server url: ${e.urls}`);let n=t[1].toLowerCase(),r=t[2].replace(/^\[|\]$/g,``),i=t[3]===void 0?Ce[n]??3478:Number(t[3]);return n===`stun`||n===`stuns`?`stun:${r}:${i}`:{hostname:r,port:i,...e.username===void 0?{}:{username:e.username},...e.credential===void 0?{}:{password:e.credential},relayType:n===`turns`?`TurnTls`:t[4]?.toLowerCase()===`tcp`?`TurnTcp`:`TurnUdp`}}function Te(e){return typeof e==`string`?e:Buffer.from(e).toString(`utf8`)}var w=class{native;fault;stateValue;closeCauseValue;closedLocally=!1;messageHandlers=new Set;stateHandlers=new Set;constructor(e,t){this.native=e,this.fault=t,this.stateValue=e.isOpen()?`open`:`connecting`,e.onOpen(()=>this.guard(()=>this.setState(`open`))),e.onClosed(()=>this.guard(()=>this.closedWith(`closed by the peer or the transport`))),e.onError(e=>this.guard(()=>this.closedWith(`error: ${e}`))),e.onMessage(e=>this.guard(()=>{if(this.closedLocally)return;let t=Te(e);for(let e of this.messageHandlers)e(t)}))}guard(e){try{e()}catch(e){this.closeCauseValue??=`handler error: ${Se(e)}`,this.fault(e)}}closedWith(e){this.closeCauseValue??=e,this.setState(`closed`)}get closeCause(){return this.closeCauseValue}setState(e){if(this.stateValue!==e&&this.stateValue!==`closed`){this.stateValue=e;for(let t of this.stateHandlers)t(e)}}get readyState(){return this.stateValue}get label(){try{return this.native.getLabel?.()??``}catch{return``}}get bufferedAmount(){try{return this.native.bufferedAmount()}catch{return 0}}send(e){if(this.stateValue!==`open`)throw Error(`data channel is not open`);this.native.sendMessage(e)}onMessage(e){return this.messageHandlers.add(e),()=>this.messageHandlers.delete(e)}onStateChange(e){return this.stateHandlers.add(e),()=>this.stateHandlers.delete(e)}close(){if(this.stateValue===`closed`)return;this.closedLocally=!0;let e=this.native;setTimeout(()=>{try{e.close()}catch{}},250).unref?.(),this.closedWith(`closed by this side`)}},T=class{native;stateValue=`new`;stateHandlers=new Set;candidateHandlers=new Set;channelHandlers=new Set;descriptionWaiters=[];hasRemoteDescription=!1;history=[];closedBy;handlerError;localCandidateCount=0;remoteCandidateCount=0;heldLocalCandidates=[];earlyCandidates=[];closed=!1;constructor(e={}){let t=(e.loadDataChannel??xe)();this.native=new t.PeerConnection(`agent`,{iceServers:(e.iceServers??[]).map(we),...e.forceTurn===!0?{iceTransportPolicy:`relay`}:{},disableAutoNegotiation:!0}),this.native.onStateChange(e=>this.guard(()=>{if(e!==this.stateValue&&this.stateValue!==`closed`){this.stateValue=e,this.remember(this.stateValue);for(let e of this.stateHandlers)e(this.stateValue)}})),this.native.onLocalCandidate((e,t)=>this.guard(()=>{let n=e.startsWith(`a=`)?e.slice(2):e;if(n.length!==0){if(!this.hasRemoteDescription){this.heldLocalCandidates.push({candidate:n,mid:t});return}this.handOut({candidate:n,mid:t})}})),this.native.onLocalDescription(e=>this.guard(()=>{for(let t of this.descriptionWaiters.splice(0))t(e)})),this.native.onDataChannel(e=>this.guard(()=>{let t=new w(e,e=>this.fault(e));for(let e of this.channelHandlers)e(t)}))}guard(e){try{e()}catch(e){this.fault(e)}}fault(e){this.closed||(this.closedBy=`handler-error`,this.handlerError=Se(e),this.close())}remember(e){this.history.length<16&&this.history.push(e)}diagnostics(){let e=C(this.native.iceState?.bind(this.native)),t=C(this.native.gatheringState?.bind(this.native)),n=C(this.native.signalingState?.bind(this.native));return{state:this.stateValue,...e===void 0?{}:{ice:e},...t===void 0?{}:{gathering:t},...n===void 0?{}:{signaling:n},history:[...this.history],...this.closedBy===void 0?{}:{closedBy:this.closedBy},...this.handlerError===void 0?{}:{handlerError:this.handlerError},localCandidates:this.localCandidateCount,remoteCandidates:this.remoteCandidateCount}}get state(){return this.stateValue}createDataChannel(e){return new w(this.native.createDataChannel(e),e=>this.fault(e))}localDescription(e){return new Promise((t,n)=>{this.descriptionWaiters.push(t);try{this.native.setLocalDescription(e)}catch(e){let r=this.descriptionWaiters.indexOf(t);r>=0&&this.descriptionWaiters.splice(r,1),n(e instanceof Error?e:Error(String(e)))}})}createOffer(){return this.localDescription(`offer`)}async acceptOffer(e){return this.native.setRemoteDescription(e,`offer`),this.remoteDescriptionApplied(),this.localDescription(`answer`)}acceptAnswer(e){this.native.setRemoteDescription(e,`answer`),this.remoteDescriptionApplied()}remoteDescriptionApplied(){this.hasRemoteDescription=!0;for(let e of this.earlyCandidates.splice(0))this.addRemoteCandidate(e);let e=this.heldLocalCandidates.splice(0);this.guard(()=>{for(let t of e)this.handOut(t)})}handOut(e){if(!this.closed){this.localCandidateCount+=1;for(let t of this.candidateHandlers)t(e)}}addRemoteCandidate(e){if(!this.closed){if(!this.hasRemoteDescription){this.earlyCandidates.length<64&&this.earlyCandidates.push(e);return}try{this.native.addRemoteCandidate(e.candidate,e.mid),this.remoteCandidateCount+=1}catch{}}}remoteFingerprint(){if(this.stateValue===`connected`)try{let e=this.native.remoteFingerprint();return e.value.length>0?e:void 0}catch{return}}onStateChange(e){return this.stateHandlers.add(e),()=>this.stateHandlers.delete(e)}onLocalCandidate(e){return this.candidateHandlers.add(e),()=>this.candidateHandlers.delete(e)}onDataChannel(e){return this.channelHandlers.add(e),()=>this.channelHandlers.delete(e)}close(){if(!this.closed){this.closed=!0,this.closedBy??=`local`;try{this.native.close()}catch{}if(this.stateValue!==`closed`){this.stateValue=`closed`,this.remember(`closed`);for(let e of this.stateHandlers)e(`closed`)}}}};function Ee(e,t){let n=t===`operator-approval`;return e.localPeer!==void 0&&t!==`local-proof`&&t!==`handoff-grant`&&!n?`local-proof`:e.handoffGrant!==void 0&&t!==`handoff-grant`&&!n?`handoff-grant`:e.connectionApproval!==void 0&&!n?`operator-approval`:null}function De(e){return typeof e==`object`&&!!e&&e.t===`handoff-grant`&&e.grant!==void 0}function E(e){return{admitted:!1,trust:`unproven`,reason:e}}async function Oe(e,t){if(t===void 0)return E(`no hand-off grant verifier is configured for this channel`);if(!De(e))return E(`expected a handoff-grant frame carrying the signed grant`);try{let n=await t.verify(e.grant);return n.admitted&&n.trust===`same-user-same-host`?E(`the grant verifier returned same-user-same-host. A cross-device grant proves the user, not the machine — see SEC-010 for what same-host requires.`):!n.admitted||t.consent===void 0||await t.consent(n)?n:E(`the person at this machine declined the transfer`)}catch(e){return E(`the grant verifier could not decide: ${e instanceof Error?e.message:`unknown error`}`)}}function ke(e){return{t:`handoff-grant`,grant:e}}function Ae(e){return typeof e==`object`&&!!e&&e.t===`local-proof`&&typeof e.nonce==`string`}function je(e){return{admitted:!1,trust:`unproven`,reason:e}}function Me(e,t){if(t===void 0)return je(`no local-peer proof is configured for this channel`);if(!Ae(e))return je(`expected a local-proof frame carrying the rendezvous nonce`);try{return t.redeem(e.nonce)}catch(e){return je(`the rendezvous ledger could not decide: ${e instanceof Error?e.message:`unknown error`}`)}}function Ne(e){return{t:`local-proof`,nonce:e}}function Pe(e,t){try{e.send(t)}catch{}}function Fe(e){try{e.close()}catch{}}function Ie(e,t,n){try{e?.(t,n)}catch{}}const D=Object.freeze({send:Pe,close:Fe,reportDeliveryError:Ie});function Le(e,t,n,r,i,a=ie){let o=a(e.cryptoContext,{secret:t,role:n,localFingerprint:e.localFingerprint,remoteFingerprint:e.remoteFingerprint,send:t=>D.send(e.channel,JSON.stringify(t)),...e.timeoutMs===void 0?{}:{timeoutMs:e.timeoutMs}});return o.result.then(r,i),o}function Re(e,t,n,r){let i=re(e.cryptoContext,{hostIdentityId:t.hostIdentityId,localFingerprint:e.localFingerprint,remoteFingerprint:e.remoteFingerprint,hostPrivateKey:t.hostPrivateKey,resolveDevicePublicKey:t.resolveDevicePublicKey,send:t=>D.send(e.channel,JSON.stringify(t)),...e.timeoutMs===void 0?{}:{timeoutMs:e.timeoutMs}});return i.result.then(n,r),i}function ze(e){return l(e).ok}function Be(e){return u(e).ok}function Ve(e){return c(e).ok}function He(e,n,i){let a=e.resumeBridge;if(a)return a.attach(t=>e.channel.send(t),{awaitResume:n,onDeliveryError:i,pendingBytes:()=>e.channel.bufferedAmount}),{onSessionMessage:e=>a.onClientMessage(e),cleanup:()=>a.detach()};let{onMessage:o,cleanup:s}=(e.createHandler??r)({session:e.session,deliver:ve(e.channel,i),maxFrameBytes:t,...e.personalUsageReporter?{personalUsageReporter:e.personalUsageReporter}:{},...e.usageReporter?{usageReporter:e.usageReporter}:{},...e.storedSessionUsageReporter?{storedSessionUsageReporter:e.storedSessionUsageReporter}:{},...e.surface?{surface:e.surface}:{},...e.commandSurfaceLocality?{commandSurfaceLocality:e.commandSurfaceLocality}:{}});return{onSessionMessage:o,cleanup:s}}var Ue=class{options;state;onSessionMessage;handlerCleanup;pairingController;reconnectController;pendingResult;pendingViaReconnect=!1;pendingDeviceId;pendingEnrollment;heldFrames=[];heldChars=0;approvalAbort;constructor(e){this.options=e,e.reconnect?this.state=`awaiting-mode`:(this.state=`pairing`,this.startFirstPair())}onInbound(e){if(this.state===`closed`)return;if(this.state===`accepted`){this.onSessionMessage?.(e);return}if(this.state===`operator-approval`){this.hold(e);return}let t;try{t=JSON.parse(e)}catch{return}if(this.state===`awaiting-mode`){Be(t)&&t.t===`rc-hello`?(this.state=`reconnecting`,this.startReconnect(),this.reconnectController?.onFrame(t)):ze(t)&&t.t===`pair-nonce`&&(this.state=`pairing`,this.startFirstPair(),this.pairingController?.onFrame(t));return}if(this.state===`pairing`){ze(t)?this.pairingController?.onFrame(t):this.hold(e);return}if(this.state===`reconnecting`){Be(t)?this.reconnectController?.onFrame(t):this.hold(e);return}if(this.state===`local-proof`){let e=Me(t,this.options.localPeer);this.options.localPeer?.onAdmission?.(e),e.admitted?this.accept(this.pendingResult,this.pendingViaReconnect):this.rejectAndClose();return}if(this.state===`handoff-grant`){this.judgeGrantFrame(t);return}if(this.state===`enrolling`){Ve(t)?this.completeEnrollment(t.spki):this.hold(e);return}}cleanup(){this.state=`closed`,this.withdrawApproval(),this.handlerCleanup?.(),this.handlerCleanup=void 0,this.onSessionMessage=void 0}onChannelClosed(){this.state!==`accepted`&&this.state!==`closed`&&this.rejectAndClose()}withdrawApproval(){this.heldFrames=[],this.heldChars=0,this.approvalAbort?.abort(),this.approvalAbort=void 0}startFirstPair(){this.pairingController=Le(this.options,this.options.secret,this.options.role,e=>this.onFirstPairAccepted(e),()=>this.rejectAndClose(),this.options.startHandshake??ie)}startReconnect(){let e=this.options.reconnect;if(!e){this.rejectAndClose();return}this.reconnectController=Re(this.options,e,e=>{this.pendingDeviceId=e.deviceId,this.accept(void 0,!0)},()=>this.rejectAndClose())}onFirstPairAccepted(e){if(this.state!==`pairing`)return;this.pendingResult=e;let t=this.options.reconnect;if(!t){this.accept(e);return}this.state=`enrolling`,D.send(this.options.channel,JSON.stringify({t:`enroll-key`,spki:t.hostPublicSpki})),this.replayHeld()}completeEnrollment(e){if(this.state===`enrolling`){if(!this.options.reconnect){this.rejectAndClose();return}(async()=>{try{await te(e);let t=await f(e);if(this.state!==`enrolling`)return;this.pendingDeviceId=t,this.pendingEnrollment={deviceId:t,spki:e},this.accept(this.pendingResult)}catch{this.rejectAndClose()}})()}}accept(e,t=!1){if(this.state===`closed`||this.state===`accepted`)return;let n=Ee(this.options,this.state);if(n!==null){this.pendingResult=e??this.pendingResult,this.pendingViaReconnect=t,this.state=n,n===`operator-approval`&&this.askOperator(),this.replayHeld();return}let r=this.pendingEnrollment;if(this.pendingEnrollment=void 0,r!==void 0)try{this.options.reconnect?.onEnroll(r.deviceId,r.spki)}catch{this.rejectAndClose();return}let i=He(this.options,t,(e,t)=>this.handleSessionDeliveryError(e,t));this.onSessionMessage=i.onSessionMessage,this.handlerCleanup=i.cleanup,this.state=`accepted`,this.options.onAccept?.(e);let a=this.heldFrames;this.heldFrames=[],this.heldChars=0;for(let e of a){if(this.state!==`accepted`)return;this.onSessionMessage?.(e)}}replayHeld(){let e=this.heldFrames;this.heldFrames=[],this.heldChars=0;for(let t of e){if(this.state===`closed`)return;this.onInbound(t)}}hold(e){this.heldChars+=e.length,this.heldFrames.push(e),(this.heldFrames.length>32||this.heldChars>262144)&&this.rejectAndClose()}async askOperator(){let e=new AbortController;this.approvalAbort=e;let t={...this.pendingDeviceId===void 0?{}:{deviceId:this.pendingDeviceId},viaReconnect:this.pendingViaReconnect,signal:e.signal},n=!1;try{n=await this.options.connectionApproval?.approve(t)===!0}catch{n=!1}this.state!==`operator-approval`||e.signal.aborted||(this.approvalAbort=void 0,n?this.accept(this.pendingResult,this.pendingViaReconnect):this.rejectAndClose())}async judgeGrantFrame(e){let t=await Oe(e,this.options.handoffGrant);this.state===`handoff-grant`&&(this.options.handoffGrant?.onAdmission?.(t),t.admitted?this.accept(this.pendingResult,this.pendingViaReconnect):this.rejectAndClose())}rejectAndClose(){this.state!==`closed`&&(this.state=`closed`,this.withdrawApproval(),D.close(this.options.channel),this.options.onReject?.())}handleSessionDeliveryError(e,t){this.state!==`closed`&&(this.state=`closed`,this.handlerCleanup?.(),this.handlerCleanup=void 0,this.onSessionMessage=void 0,D.reportDeliveryError(this.options.onDeliveryError,e,t),D.close(this.options.channel))}};function We(e){return Object.assign(Error(`WebRtcTransport ${e}.`),{name:`TransportLifecycleError`,code:e,transportName:`webrtc`})}var Ge=class{options;generation=0;paired=!1;dropped=!1;constructor(e){this.options=e}reset(e){this.generation=e,this.paired=!1,this.dropped=!1}accept(e){e===this.generation&&(this.paired=!0)}handleDrop(e){e!==this.generation||!this.paired||this.dropped||(this.dropped=!0,this.options.cleanup(),this.options.onDropped())}handleFailure(e,t,n,r){if(t!==this.generation||this.dropped)return;let i=this.paired;i&&(this.dropped=!0);try{this.options.onDeliveryError(n,r)}catch{}this.options.cleanup();try{e.close()}catch{}i&&this.options.onDropped()}},Ke=class{options;name=`webrtc`;lifecycle=Object.freeze({kind:`service`});defaultEnabled=!1;optionsSchema={};session;peer;unsubscribeSignal;cleanupHandler;generation=0;localFingerprint;pairingGate;offerSent=!1;localCandidates=[];answered=!1;pendingFrames=[];stopAwaitingCertificate;deliveryLifecycle;constructor(e){if(this.options=e,this.deliveryLifecycle=new Ge({cleanup:()=>{this.cleanupHandler?.(),this.pairingGate?.cleanup()},onDropped:()=>this.options.onDropped?.(),onDeliveryError:(e,t)=>this.options.onDeliveryError?.(e,t)}),this.options.secret&&this.options.open===!0)throw Error("WebRtcTransport: `secret` and `open: true` are contradictory. A pairing secret gates the data channel; `open` runs without a gate. Pass one.");if(this.options.secret===void 0||this.options.secret===``){if(this.options.open!==!0)throw Error('WebRtcTransport: no pairing `secret` and no explicit `open`. Pass a `secret` to gate the data channel, or `{ open: true, openReason: "…" }` to run without pairing on purpose.');i({open:!0,...this.options.openReason===void 0?{}:{openReason:this.options.openReason}})}}validateOptions(){return!0}attach(e){this.session=e}createPeer(){return new T({...this.options.iceServers?{iceServers:this.options.iceServers}:{},...this.options.forceTurn?{forceTurn:!0}:{},...this.options.loadDataChannel?{loadDataChannel:this.options.loadDataChannel}:{}})}wireSignaling(e,t,n,r){let i=this.options.signaling;e.onLocalCandidate(t=>{r===this.generation&&e===this.peer&&(this.offerSent?this.sendCandidate(t):this.localCandidates.length<64&&this.localCandidates.push(t))});let a=Promise.resolve();this.unsubscribeSignal=i.onSignal(i=>{r===this.generation&&(a=a.then(async()=>{if(r===this.generation&&e===this.peer){if(i.kind===`answer`){if(this.answered)return;this.answered=!0;let a=this.remoteFingerprintAlgorithm(t,i.data);if(this.options.secret&&a===void 0)return;let o=i.data?.sdp;if(typeof o!=`string`)return;e.acceptAnswer(o),a!==void 0&&this.awaitVerifiedCertificate(e,t,n,a,r)}else if(i.kind===`ice`){let t=qe(i.data);t!==void 0&&e.addRemoteCandidate(t)}}}).catch(()=>{r===this.generation&&this.failPairing(t)}))})}sendCandidate(e){this.options.signaling.send({kind:`ice`,data:{candidate:e.candidate,sdpMid:e.mid,sdpMLineIndex:0}})}requireCurrentPeer(e,t){if(t!==this.generation||this.peer!==e)throw e.close(),Error(`WebRtcTransport startup was stopped.`)}async start(){let e=this.session;if(!e)throw We(`not-attached`);if(this.peer)throw We(`already-started`);let t=++this.generation;this.deliveryLifecycle.reset(t),this.answered=!1,this.offerSent=!1,this.localCandidates=[],this.pendingFrames=[];let n=this.createPeer();this.peer=n;let r=this.options.signaling,i=n.createDataChannel(`agent-session`);this.wireChannel(i,e,t),this.wireSignaling(n,i,e,t);let a=await n.createOffer();this.requireCurrentPeer(n,t),this.options.secret&&(this.localFingerprint=p(a)),r.send({kind:`offer`,data:{type:`offer`,sdp:a}}),this.offerSent=!0;for(let e of this.localCandidates.splice(0))this.sendCandidate(e)}remoteFingerprintAlgorithm(e,t){if(!this.options.secret)return;let n=t.sdp;try{if(typeof n!=`string`)throw Error(`answer carries no SDP`);return m(n).algorithm}catch{this.failPairing(e);return}}failPairing(e){e.close(),this.options.onPairingFailed?.()}awaitVerifiedCertificate(e,t,n,r,i){this.stopAwaitingCertificate=S(e,r,e=>{if(i!==this.generation)return;if(t.readyState===`open`){this.startPairing(t,n,e,i);return}let r=t.onStateChange(a=>{a===`open`&&i===this.generation&&(r(),this.startPairing(t,n,e,i))})},()=>{i===this.generation&&this.failPairing(t)})}startPairing(e,t,n,r){let i=this.options.secret;if(!i||!this.localFingerprint)return;this.pairingGate=new Ue({cryptoContext:this.options.cryptoContext,channel:{send:t=>e.send(t),close:()=>e.close()},session:t,secret:i,role:`initiator`,localFingerprint:this.localFingerprint,remoteFingerprint:n,onAccept:e=>{r===this.generation&&(this.deliveryLifecycle.accept(r),this.options.onPaired?.(e))},...this.options.onPairingFailed?{onReject:this.options.onPairingFailed}:{},...this.options.reconnect?{reconnect:this.options.reconnect}:{},...this.options.localPeer?{localPeer:this.options.localPeer}:{},...this.options.connectionApproval?{connectionApproval:this.options.connectionApproval}:{},...this.options.resumeBridge?{resumeBridge:this.options.resumeBridge}:{},...this.options.personalUsageReporter?{personalUsageReporter:this.options.personalUsageReporter}:{},...this.options.usageReporter?{usageReporter:this.options.usageReporter}:{},...this.options.storedSessionUsageReporter?{storedSessionUsageReporter:this.options.storedSessionUsageReporter}:{},surface:`remote`,commandSurfaceLocality:`remote`,onDeliveryError:(t,n)=>this.deliveryLifecycle.handleFailure(e,r,t,n)});let a=this.pairingGate;for(let e of this.pendingFrames.splice(0))a.onInbound(e)}wireChannel(e,n,i){if(this.options.secret){e.onMessage(e=>{i===this.generation&&(this.pairingGate?this.pairingGate.onInbound(e):this.pendingFrames.length<16&&this.pendingFrames.push(e))}),e.onStateChange(e=>{i===this.generation&&e===`closed`&&(this.pairingGate?.onChannelClosed(),this.deliveryLifecycle.handleDrop(i))}),this.cleanupHandler=()=>this.pairingGate?.cleanup();return}let{onMessage:a,cleanup:o}=r({session:n,deliver:ve(e,(t,n)=>this.deliveryLifecycle.handleFailure(e,i,t,n)),...this.options.personalUsageReporter?{personalUsageReporter:this.options.personalUsageReporter}:{},...this.options.usageReporter?{usageReporter:this.options.usageReporter}:{},...this.options.storedSessionUsageReporter?{storedSessionUsageReporter:this.options.storedSessionUsageReporter}:{},surface:`remote`,commandSurfaceLocality:`remote`,maxFrameBytes:t});this.cleanupHandler=o,e.onMessage(e=>{i===this.generation&&a(e)})}async stop(){this.generation+=1,this.cleanupHandler?.(),this.unsubscribeSignal?.(),this.cleanupHandler=void 0,this.unsubscribeSignal=void 0,this.pairingGate=void 0,this.localFingerprint=void 0,this.answered=!1,this.offerSent=!1,this.localCandidates=[],this.pendingFrames=[],this.stopAwaitingCertificate?.(),this.stopAwaitingCertificate=void 0,this.deliveryLifecycle.reset(this.generation),this.peer&&=(this.peer.close(),void 0),this.session=void 0}};function qe(e){if(typeof e!=`object`||!e)return;let t=e;if(typeof t.candidate!=`string`||t.candidate.length===0)return;let n=typeof t.sdpMid==`string`?t.sdpMid:typeof t.sdpMLineIndex==`number`?String(t.sdpMLineIndex):`0`;return{candidate:t.candidate,mid:n}}function Je(){let e=[],t=[],n=!0;function r(e,t){return{send(e){n&&queueMicrotask(()=>{for(let n of t)n(e)})},onSignal(t){return e.push(t),()=>{let n=e.indexOf(t);n>=0&&e.splice(n,1)}},close(){n=!1,e.length=0}}}return[r(e,t),r(t,e)]}const Ye=new Set([`offer`,`answer`,`ice`]);function Xe(e){return new g(e)}var Ze=class{options;socket;handlers=[];outbox=[];joined=!1;closed=!1;constructor(e){this.options=e;let t=e.createSocket??Xe;this.socket=t(e.url),this.socket.on(`open`,()=>this.handleOpen()),this.socket.on(`message`,e=>this.handleMessage(e)),this.socket.on(`error`,e=>this.fail(e instanceof Error?e:Error(String(e)))),this.socket.on(`close`,()=>this.handleClose())}handleOpen(){this.socket.send(JSON.stringify({type:`join`,rendezvous:this.options.rendezvous}));for(let e of this.outbox)this.writeSignal(e);this.outbox.length=0}handleMessage(e){let t;try{t=JSON.parse(typeof e==`string`?e:String(e))}catch{return}if(typeof t!=`object`||!t)return;let n=t;if(n.type===`joined`){this.joined=!0,this.options.onReady?.();return}if(n.type===`error`){this.fail(Error(`signaling relay rejected the connection: ${String(n.reason)}`));return}if(n.type===`signal`&&typeof n.kind==`string`&&Ye.has(n.kind)){let e={kind:n.kind,data:n.data};for(let t of this.handlers)t(e)}}handleClose(){this.closed||this.joined||this.fail(Error(`signaling socket closed before the rendezvous was joined`))}fail(e){this.options.onError?.(e)}writeSignal(e){this.socket.send(JSON.stringify({type:`signal`,kind:e.kind,data:e.data}))}send(e){this.closed||(this.socket.readyState===1?this.writeSignal(e):this.outbox.push(e))}onSignal(e){return this.handlers.push(e),()=>{let t=this.handlers.indexOf(e);t>=0&&this.handlers.splice(t,1)}}close(){this.closed=!0,this.handlers.length=0,this.outbox.length=0,this.socket.close()}};const Qe=/^[A-Za-z0-9_-]{22}$/,$e=6e4;function O(e){return typeof e==`string`&&Qe.test(e)}function k(e,t){return typeof e==`string`&&e.length>0&&e.length<=t}function et(e){if(typeof e!=`object`||!e||Array.isArray(e))return;let t=e;if(!(t.v!==1||!O(t.from))){if(t.kind===`hello`)return{v:1,kind:`hello`,from:t.from};if(!(!O(t.to)||!O(t.cid))){if(t.kind===`offer`||t.kind===`answer`)return k(t.sdp,49152)?{v:1,kind:t.kind,from:t.from,to:t.to,cid:t.cid,sdp:t.sdp}:void 0;if(t.kind===`ice`){let e=t.candidate;if(typeof e!=`object`||!e||Array.isArray(e))return;let n=e;return!k(n.candidate,2048)||n.sdpMid!==void 0&&!k(n.sdpMid,64)||n.sdpMLineIndex!==void 0&&!(typeof n.sdpMLineIndex==`number`&&Number.isInteger(n.sdpMLineIndex)&&n.sdpMLineIndex>=0&&n.sdpMLineIndex<64)?void 0:{v:1,kind:`ice`,from:t.from,to:t.to,cid:t.cid,candidate:{candidate:n.candidate,...n.sdpMid===void 0?{}:{sdpMid:n.sdpMid},...n.sdpMLineIndex===void 0?{}:{sdpMLineIndex:n.sdpMLineIndex}}}}}}}function tt(e){if(typeof e!=`object`||!e||Array.isArray(e))return;let t=e;if(!(t.t!==`mesh-msg`||typeof t.body!=`string`||t.body.length>6e4))return{t:`mesh-msg`,body:t.body}}var nt=class extends Error{end;stage;role;peer;channelClose;cause;constructor(e){let t=[`mesh link ended (${e.end}) during ${e.stage} as ${e.role}`];e.detail!==void 0&&t.push(e.detail),e.cause!==void 0&&t.push(e.cause instanceof Error?e.cause.message:String(e.cause));let n=e.peer;n!==void 0&&t.push(`connection ${n.state} [${n.history.join(` > `)}], ice ${n.ice??`?`}, gathering ${n.gathering??`?`}, candidates ${n.localCandidates} sent / ${n.remoteCandidates} applied, closed by ${n.closedBy??`the peer or the network`}${n.handlerError===void 0?``:` (${n.handlerError})`}`),e.channelClose!==void 0&&t.push(`channel ${e.channelClose}`),super(t.join(`; `)),this.name=`MeshLinkEndedError`,this.end=e.end,this.stage=e.stage,this.role=e.role,n!==void 0&&(this.peer=n),e.channelClose!==void 0&&(this.channelClose=e.channelClose),e.cause!==void 0&&(this.cause=e.cause)}};const rt=`agent-file`,it=JSON.stringify({t:`mesh-admitted`});var at=class{options;state=`connecting`;peer;channel;localFingerprint;remoteFingerprint;tookRemoteDescription=!1;creatingPeer=!1;sentDescription=!1;localCandidates=[];remoteCandidates=0;handshake;fedProof=!1;held=[];handlers=new Set;endHandlers=new Set;fileChannels=new Set;fileHandlers=new Set;signalChain=Promise.resolve();stopAwaitingCertificate;timer;admissionResult;constructor(e){this.options=e,this.timer=setTimeout(()=>this.end(`timeout`),e.connectTimeoutMs)}get role(){return this.options.role}get admitted(){return this.state===`admitted`}get ended(){return this.isEnded()}isEnded(){return this.state===`ended`}get admission(){return this.state===`admitted`?this.admissionResult:void 0}get channelBinding(){if(this.state===`admitted`&&this.localFingerprint!==void 0&&this.remoteFingerprint!==void 0)return{localFingerprint:this.localFingerprint,remoteFingerprint:this.remoteFingerprint}}async offer(){if(!(this.options.role!==`offerer`||this.creatingPeer||this.isEnded())){this.creatingPeer=!0;try{let e=await this.createPeer();if(e===void 0)return;this.adoptChannel(e.createDataChannel(`agent-mesh`));let t=await e.createOffer();if(this.isEnded())return;this.localFingerprint=p(t),this.sendDescription({kind:`offer`,sdp:t})}catch(e){this.end(`signaling`,e)}}}onSignal(e){this.isEnded()||(this.signalChain=this.signalChain.then(()=>this.applySignal(e)).catch(e=>this.end(`signaling`,e)))}async applySignal(e){if(this.isEnded())return;if(e.kind===`ice`){if(!this.tookRemoteDescription||!this.peer||++this.remoteCandidates>64)return;this.peer.addRemoteCandidate({candidate:e.candidate.candidate,mid:e.candidate.sdpMid??String(e.candidate.sdpMLineIndex??0)});return}let t=this.options.role===`offerer`?`answer`:`offer`;if(e.kind!==t||this.tookRemoteDescription)return;this.tookRemoteDescription=!0;let n;try{n=m(e.sdp).algorithm}catch(e){this.end(`channel-binding`,e);return}if(this.options.role===`offerer`){let t=this.peer;if(!t)return;t.acceptAnswer(e.sdp),this.awaitCertificate(t,n);return}let r=await this.createPeer();if(r===void 0)return;let i=await r.acceptOffer(e.sdp);this.isEnded()||(this.localFingerprint=p(i),this.sendDescription({kind:`answer`,sdp:i}),this.awaitCertificate(r,n))}async createPeer(){let e=await this.options.createPeer();if(this.isEnded()){e.close();return}return this.peer=e,e.onLocalCandidate(e=>{if(this.isEnded())return;let t={kind:`ice`,candidate:{candidate:e.candidate,sdpMid:e.mid}};this.sentDescription?this.options.sendSignal(t):this.localCandidates.length<64&&this.localCandidates.push(t)}),e.onStateChange(e=>{(e===`failed`||e===`closed`)&&this.end(`closed`,void 0,`connection ${e}`)}),e.onDataChannel(e=>this.incomingChannel(e)),e}incomingChannel(e){if(this.options.role===`answerer`&&this.channel===void 0&&!this.isEnded()){this.adoptChannel(e);return}if(this.state!==`admitted`||e.label!==rt||this.fileHandlers.size===0||this.fileChannels.size>=4){e.close();return}this.trackFileChannel(e);for(let t of this.fileHandlers)t(e)}trackFileChannel(e){this.fileChannels.add(e),e.onStateChange(t=>{t===`closed`&&this.fileChannels.delete(e)})}openFileChannel(){let e=this.peer;if(this.state!==`admitted`||e===void 0)return Promise.reject(Error(`mesh link is not admitted`));if(this.fileChannels.size>=4)return Promise.reject(Error(`too many file transfers are open on this link`));let t=e.createDataChannel(rt);return this.trackFileChannel(t),new Promise((e,n)=>{if(t.readyState===`open`){e(t);return}let r=setTimeout(()=>{i(),t.close(),n(Error(`the file channel did not open`))},1e4),i=t.onStateChange(a=>{a!==`connecting`&&(clearTimeout(r),i(),a===`open`?e(t):n(Error(`the file channel closed before it opened`)))})})}onFileChannel(e){return this.fileHandlers.add(e),()=>this.fileHandlers.delete(e)}sendDescription(e){this.options.sendSignal(e),this.sentDescription=!0;for(let e of this.localCandidates.splice(0))this.options.sendSignal(e)}awaitCertificate(e,t){this.stopAwaitingCertificate=S(e,t,e=>{this.isEnded()||(this.remoteFingerprint=e,this.maybeStartHandshake())},e=>this.end(`channel-binding`,Error(e)))}adoptChannel(e){this.channel=e,e.onMessage(e=>this.inbound(e)),e.onStateChange(e=>{e===`open`?this.maybeStartHandshake():e===`closed`&&this.end(`closed`,void 0,`data channel closed`)}),e.readyState===`open`&&this.maybeStartHandshake()}maybeStartHandshake(){let e=this.channel;if(this.state!==`connecting`||this.handshake!==void 0||e===void 0||this.localFingerprint===void 0||this.remoteFingerprint===void 0||e.readyState!==`open`)return;let t;try{t=this.options.startHandshake({localFingerprint:this.localFingerprint,remoteFingerprint:this.remoteFingerprint,send:e=>this.write(JSON.stringify(e))})}catch(e){this.end(`handshake`,e);return}this.handshake=t,t.result.then(e=>this.confirm(e),e=>this.end(`handshake`,e));let n=this.held.splice(0);for(let e of n)this.feed(e)}inbound(e){if(!this.isEnded()){if(this.state===`admitted`){this.deliver(e);return}if(this.state===`confirming`){this.confirmed(e);return}if(this.handshake===void 0){this.hold(e);return}this.feed(e)}}hold(e){if(this.held.length>=16){this.end(`protocol`);return}this.held.push(e)}feed(e){if(this.fedProof){this.hold(e);return}let t;try{t=JSON.parse(e)}catch{t=e}typeof t==`object`&&t&&t.t===`dh-prove`&&(this.fedProof=!0),this.handshake?.onFrame(t)}confirm(e){if(this.state!==`connecting`)return;if(this.options.accepts!==void 0&&!this.options.accepts(e)){this.end(`handshake`,Error(`the admitted device is not the one this link is for`));return}this.state=`confirming`,this.admissionResult=e,this.write(it);let t=this.held.splice(0);for(let e of t)this.inbound(e)}confirmed(e){let t;try{t=JSON.parse(e)}catch{t=void 0}let n=this.admissionResult;if(n===void 0||typeof t!=`object`||!t||t.t!==`mesh-admitted`){this.end(`protocol`);return}clearTimeout(this.timer),this.state=`admitted`,this.options.onAdmitted(n)}deliver(e){let t;try{t=JSON.parse(e)}catch{t=void 0}let n=tt(t);if(n===void 0){this.end(`protocol`);return}for(let e of this.handlers)e(n.body)}write(e){try{this.channel?.send(e)}catch(e){this.end(`closed`,e)}}send(e){if(this.state!==`admitted`)throw Error(`mesh link is not admitted`);if(e.length>6e4)throw Error(`mesh message exceeds ${$e} characters`);this.write(JSON.stringify({t:`mesh-msg`,body:e}))}onMessage(e){return this.handlers.add(e),()=>this.handlers.delete(e)}onEnd(e){return this.endHandlers.add(e),()=>this.endHandlers.delete(e)}close(){this.end(`closed`,void 0,`closed by this side`)}get stage(){return this.state===`admitted`||this.state===`confirming`?this.state:this.handshake===void 0?this.remoteFingerprint===void 0?this.tookRemoteDescription?`connecting`:`signaling`:`awaiting-channel`:`handshake`}end(e,t,n){if(this.isEnded())return;let r=new nt({end:e,stage:this.stage,role:this.options.role,...n===void 0?{}:{detail:n},...this.peer===void 0?{}:{peer:this.peer.diagnostics()},...this.channel?.closeCause===void 0?{}:{channelClose:this.channel.closeCause},...t===void 0?{}:{cause:t}});this.state=`ended`,clearTimeout(this.timer),this.stopAwaitingCertificate?.(),this.held.length=0,this.handshake?.onFrame(void 0),this.channel?.close();for(let e of this.fileChannels)e.close();this.fileChannels.clear(),this.fileHandlers.clear();let i=this.peer;i&&setTimeout(()=>i.close(),250).unref?.(),this.options.onEnded(e,r);for(let t of this.endHandlers)t(e);this.endHandlers.clear(),this.handlers.clear()}};const A=554869826,j={Binding:1,Allocate:3,Refresh:4,Send:6,Data:7,CreatePermission:8,ChannelBind:9},M={Request:0,Indication:1,Success:2,Error:3},N={MappedAddress:1,Username:6,MessageIntegrity:8,ErrorCode:9,UnknownAttributes:10,ChannelNumber:12,Lifetime:13,XorPeerAddress:18,Data:19,Realm:20,Nonce:21,XorRelayedAddress:22,RequestedAddressFamily:23,EvenPort:24,RequestedTransport:25,DontFragment:26,MessageIntegritySha256:28,PasswordAlgorithm:29,Userhash:30,XorMappedAddress:32,ReservationToken:34,Priority:36,UseCandidate:37,Fingerprint:32808};function ot(e,t){return e&15|(e&112)<<1|(e&3968)<<2|(t&1)<<4|(t&2)<<7}function st(e){return e.length>=20&&(e[0]&192)==0&&e.readUInt32BE(4)===554869826}function ct(e){if(!st(e))return;let t=e.readUInt16BE(0),n=e.readUInt16BE(2);if(n%4!=0||20+n>e.length)return;let r=t&15|(t&224)>>1|(t&15872)>>2,i=(t&16)>>4|(t&256)>>7,a=[],o=20,s=20+n;for(;o<s;){if(o+4>s)return;let t=e.readUInt16BE(o),n=e.readUInt16BE(o+2);if(o+4+n>s)return;a.push({type:t,value:e.subarray(o+4,o+4+n),offset:o}),o+=4+n+(4-n%4)%4}if(o===s)return{method:r,cls:i,transactionId:Buffer.from(e.subarray(8,20)),attributes:a,raw:e.subarray(0,s)}}function P(e,t){return e.attributes.find(e=>e.type===t)?.value}function lt(e,t){return e.attributes.filter(e=>e.type===t).map(e=>e.value)}function ut(e){let t=e.attributes.findIndex(e=>e.type===N.MessageIntegrity);return t<0?e:{...e,attributes:e.attributes.slice(0,t+1)}}function dt(e,t){if(e.length<8)return;let n=e[1],r=e.readUInt16BE(2)^A>>>16;if(n===1&&e.length===8){let t=e.readUInt32BE(4)^A;return{address:[t>>>24,t>>>16&255,t>>>8&255,t&255].join(`.`),port:r}}if(n===2&&e.length===20){let n=Buffer.alloc(16);n.writeUInt32BE(A,0),t.copy(n,4);let i=[];for(let t=0;t<16;t+=2)i.push(((e.readUInt16BE(4+t)^n.readUInt16BE(t))&65535).toString(16));return{address:i.join(`:`),port:r}}}function ft(e){let[t=``,n=``]=e.split(`::`),r=t.length>0?t.split(`:`):[],i=e.includes(`::`)&&n.length>0?n.split(`:`):[],a=e.includes(`::`)?[...r,...Array(8-r.length-i.length).fill(`0`),...i]:r,o=Buffer.alloc(16);return a.forEach((e,t)=>o.writeUInt16BE(parseInt(e,16)&65535,t*2)),o}function F(e,t){let n=(e.port^A>>>16)&65535;if(b(e.address)){let t=Buffer.alloc(8);t[1]=1,t.writeUInt16BE(n,2);let r=e.address.split(`.`).reduce((e,t)=>e<<8|Number(t),0);return t.writeUInt32BE((r^A)>>>0,4),t}if(!pe(e.address))throw Error(`not an IP address: ${e.address}`);let r=Buffer.alloc(20);r[1]=2,r.writeUInt16BE(n,2);let i=Buffer.alloc(16);i.writeUInt32BE(A,0),t.copy(i,4);let a=ft(e.address);for(let e=0;e<16;e+=1)r[4+e]=a[e]^i[e];return r}function pt(e,t,n){return _(`md5`).update(`${e}:${t}:${n}`,`utf8`).digest()}function mt(e,t){let n=e.attributes.find(e=>e.type===N.MessageIntegrity);if(n===void 0||n.value.length!==20)return!1;let r=Buffer.from(e.raw.subarray(0,n.offset));return r.writeUInt16BE(n.offset-20+24,2),y(v(`sha1`,t).update(r).digest(),n.value)}const ht=(()=>{let e=new Uint32Array(256);for(let t=0;t<256;t+=1){let n=t;for(let e=0;e<8;e+=1)n=n&1?3988292384^n>>>1:n>>>1;e[t]=n>>>0}return e})();function gt(e){let t=4294967295;for(let n of e)t=ht[(t^n)&255]^t>>>8;return(t^4294967295)>>>0}function I(e,t,n,r,i={}){let a=[],o=Buffer.alloc(20);o.writeUInt16BE(ot(e,t),0),o.writeUInt32BE(A,4),n.copy(o,8,0,12),a.push(o);let s=(e,t)=>{let n=Buffer.alloc(4);n.writeUInt16BE(e,0),n.writeUInt16BE(t.length,2),a.push(n,t,Buffer.alloc((4-t.length%4)%4))};for(let e of r)s(e.type,e.value);let c=()=>Buffer.concat(a);if(i.integrityKey!==void 0){let e=c();e.writeUInt16BE(e.length-20+24,2),s(N.MessageIntegrity,v(`sha1`,i.integrityKey).update(e).digest())}if(i.fingerprint!==!1){let e=c();e.writeUInt16BE(e.length-20+8,2);let t=Buffer.alloc(4);t.writeUInt32BE((gt(e)^1398035790)>>>0,0),s(N.Fingerprint,t)}let l=c();if(l.writeUInt16BE(l.length-20,2),l.length>65535)throw Error(`STUN message too large`);return l}function _t(e,t){let n=Buffer.from(t,`utf8`),r=Buffer.alloc(4+n.length);return r[2]=Math.floor(e/100),r[3]=e%100,n.copy(r,4),r}function L(e){let t=Buffer.alloc(4);return t.writeUInt32BE(e>>>0,0),t}function vt(e){return e.length>=4&&(e[0]&192)==64}function yt(e){if(!vt(e))return;let t=e.readUInt16BE(0),n=e.readUInt16BE(2);if(!(4+n>e.length))return{channel:t,payload:e.subarray(4,4+n)}}function bt(e,t){let n=Buffer.alloc(4);return n.writeUInt16BE(e,0),n.writeUInt16BE(t.length,2),Buffer.concat([n,t,Buffer.alloc((4-t.length%4)%4)])}const xt={allocationsPerOwner:8,totalAllocations:64,bytesPerSecondPerOwner:1024*1024,maxLifetimeSeconds:3600,maxAllocationAgeMs:720*60*1e3,permissionsPerAllocation:32,channelsPerAllocation:32},St={perSourcePerSecond:10,totalPerSecond:2e3},Ct=3e5,wt=new Set([N.MappedAddress,N.Username,N.MessageIntegrity,N.ErrorCode,N.ChannelNumber,N.Lifetime,N.XorPeerAddress,N.Data,N.Realm,N.Nonce,N.RequestedAddressFamily,N.RequestedTransport,N.MessageIntegritySha256,N.PasswordAlgorithm,N.XorMappedAddress,N.Priority,N.UseCandidate]);function R(e){return`${e.address}:${e.port}`}function Tt(){for(let e of Object.values(x()))for(let t of e??[])if(t.family===`IPv4`&&!t.internal)return t.address;return`127.0.0.1`}function Et(e){return e.startsWith(`127.`)||e===`::1`}function Dt(e){let[t=0,n=0]=e.split(`.`).map(Number);return t===10||t===172&&n>=16&&n<=31||t===192&&n===168||t===169&&n===254||t===100&&n>=64&&n<=127}function Ot(e,t){return n=>{if(!b(n))return!1;let r=Number(n.split(`.`)[0]);return r===0||r>=224?!1:r===127?e:t||!Dt(n)}}async function kt(e,t){let n=fe(`udp4`);try{return await new Promise((r,i)=>{n.once(`error`,i),n.bind(e,t,()=>{n.off(`error`,i),r()})}),n}catch(e){try{n.close()}catch{}throw e}}async function At(e,t){try{return await kt(e,t)}catch{return}}function jt(e,t,n){let r=e instanceof Error?e.code:void 0,i=r===`EADDRINUSE`?`the port is taken`:r===`EADDRNOTAVAIL`?`${t} is not an address of this machine`:r===`EACCES`?`port ${n} needs privileges this process does not have`:Nt(e).message;return Error(`the TURN relay cannot listen on UDP ${t}:${n}: ${i}`,{cause:e})}function Mt(){let e=new Set;for(let t of Object.values(x()))for(let n of t??[])e.add(n.address);return e}function z(e,t,n,r=1){let i=Math.max(0,n-e.at);return e.tokens=Math.min(Math.max(t,r),e.tokens+i/1e3*t),e.at=n,e.tokens>=r}function Nt(e){return e instanceof Error?e:Error(String(e))}var Pt=class e{socket;options;bindHost;relayAddress;allocations=new Map;buckets=new Map;quotas;realm;limits;answerBuckets=new Map;answerBudget;nonceSecret=le(32);ownAddresses=Mt();allowPeer;sweeper;retained;closed=!1;constructor(e,t,n,r){this.socket=e,this.options=t,this.bindHost=n,this.relayAddress=r,this.quotas={...xt,...t.quotas},this.realm=t.realm??`r`,this.limits={...St,...t.unauthenticatedLimits},this.allowPeer=t.allowPeer??Ot(Et(r),t.allowPrivatePeers??!0),e.on(`message`,(e,t)=>this.receive(e,t)),e.on(`error`,e=>t.onError?.(e)),this.sweeper=setInterval(()=>this.sweep(),5e3),this.sweeper.unref?.()}static async start(t){let n=Buffer.byteLength(t.realm??`r`);if(n===0||n>4)throw Error(`TURN realm must be 1 to 4 bytes`);let r=t.host??`0.0.0.0`,i=t.port??3478,a;try{a=await kt(i,r)}catch(e){throw jt(e,r,i)}let o=t.relayAddress??(r===`0.0.0.0`?Tt():r);return new e(a,t,r,o)}get address(){let e=this.socket.address();return{address:this.bindHost===`0.0.0.0`?this.relayAddress:e.address,port:e.port}}allocationCount(e){if(e===void 0)return this.allocations.size;let t=0;for(let n of this.allocations.values())n.owner===e&&(t+=1);return t}retain(e){this.retained=new Set(e);for(let t of[...this.allocations.values()])e.has(t.owner)||this.remove(t);for(let t of[...this.buckets.keys()])e.has(t)||this.buckets.delete(t)}close(){if(this.closed)return Promise.resolve();this.closed=!0,clearInterval(this.sweeper);for(let e of[...this.allocations.values()])this.remove(e);return new Promise(e=>this.socket.close(()=>e()))}now(){return(this.options.now??Date.now)()}receive(e,t){if(this.closed)return;if(vt(e)){this.fromClientChannel(e,t);return}let n=ct(e);if(n!==void 0){if(n.cls===M.Indication){n.method===j.Send&&this.fromClientSend(n,t);return}n.cls===M.Request&&this.request(n,t).catch(e=>this.options.onError?.(Nt(e)))}}send(e,t){this.closed||this.socket.send(e,t.port,t.address,e=>{e&&this.options.onError?.(e)})}reply(e,t,n,r){let i=I(e.method,M.Success,e.transactionId,n,{...r===void 0?{}:{integrityKey:r}});return this.send(i,t),i}fail(e,t,n,r,i=[],a){let o=I(e.method,M.Error,e.transactionId,[{type:N.ErrorCode,value:_t(n,r)},...i],{...a===void 0?{}:{integrityKey:a}});this.send(o,t)}nonce(e){let t=Buffer.alloc(4);return t.writeUInt32BE(Math.floor(this.now()/1e3)>>>0,0),Buffer.concat([t,this.nonceMac(t,e)]).toString(`base64url`)}nonceMac(e,t){return v(`sha256`,this.nonceSecret).update(e).update(R(t)).digest().subarray(0,8)}nonceValid(e,t){if(!/^[A-Za-z0-9_-]{16}$/.test(e))return!1;let n=Buffer.from(e,`base64url`),r=n.subarray(0,4);if(!y(n.subarray(4),this.nonceMac(r,t)))return!1;let i=this.now()-r.readUInt32BE(0)*1e3;return i>=-6e4&&i<=6e5}answerUnauthenticated(e,t,n,r){let i=this.now(),a=this.answerBudget??={tokens:this.limits.totalPerSecond,at:i},o=this.answerBuckets.get(t.address)??{tokens:this.limits.perSourcePerSecond,at:i};if(this.answerBuckets.set(t.address,o),e.raw.length<28||!z(o,this.limits.perSourcePerSecond,i)||!z(a,this.limits.totalPerSecond,i))return;let s=I(e.method,n,e.transactionId,r(),{fingerprint:!1});s.length>e.raw.length||(--o.tokens,--a.tokens,this.send(s,t))}refuseUnauthenticated(e,t,n,r=()=>[]){this.answerUnauthenticated(e,t,M.Error,()=>[{type:N.ErrorCode,value:_t(n,``)},...r()])}challenge(e,t,n){this.refuseUnauthenticated(e,t,n,()=>[{type:N.Realm,value:Buffer.from(this.realm)},{type:N.Nonce,value:Buffer.from(this.nonce(t))}])}async authenticate(e,t,n){if(P(e,N.MessageIntegrity)===void 0){this.challenge(e,t,401);return}let r=P(e,N.Username)?.toString(`utf8`),i=P(e,N.Realm)?.toString(`utf8`),a=P(e,N.Nonce)?.toString(`utf8`);if(r===void 0||i===void 0||a===void 0){this.refuseUnauthenticated(e,t,400);return}if(i!==this.realm){this.challenge(e,t,401);return}if(!this.nonceValid(a,t)){this.challenge(e,t,438);return}if(n!==void 0){if(r!==n.username){this.refuseUnauthenticated(e,t,441);return}if(!mt(e,n.integrityKey)){this.challenge(e,t,401);return}return{auth:{owner:n.owner,password:``},key:n.integrityKey,username:r}}let o;try{o=await this.options.authorize(r)}catch{o=void 0}if(this.closed)return;let s=o===void 0?void 0:pt(r,this.realm,o.password);if(o===void 0||s===void 0||!mt(e,s)){this.challenge(e,t,401);return}return{auth:o,key:s,username:r}}unknownAttributes(e){return e.attributes.map(e=>e.type).filter(e=>e<32768&&!wt.has(e))}async request(e,t){let n={address:t.address,port:t.port};if(e.method===j.Binding){this.answerUnauthenticated(e,n,M.Success,()=>[{type:N.XorMappedAddress,value:F(n,e.transactionId)}]);return}if(![j.Allocate,j.Refresh,j.CreatePermission,j.ChannelBind].includes(e.method)){this.refuseUnauthenticated(e,n,400);return}let r=this.allocations.get(R(n)),i=this.live(r)?r:void 0;if(e.method===j.Allocate&&i!==void 0&&i.transactionId.equals(e.transactionId)){i.response.length<=e.raw.length&&this.send(i.response,n);return}let a=await this.authenticate(e,n,i);a!==void 0&&await this.authenticatedRequest(ut(e),n,a)}async authenticatedRequest(e,t,n){let{key:r}=n,i=this.unknownAttributes(e);if(i.length>0){let n=Buffer.alloc(i.length*2);i.forEach((e,t)=>n.writeUInt16BE(e,t*2)),this.fail(e,t,420,`Unknown Attribute`,[{type:N.UnknownAttributes,value:n}],r);return}let a=this.allocations.get(R(t)),o=this.live(a)?a:void 0;if(e.method===j.Allocate){await this.allocate(e,t,n,o);return}if(o===void 0||o.owner!==n.auth.owner){this.fail(e,t,437,`Allocation Mismatch`,[],r);return}e.method===j.Refresh?this.refresh(e,t,o):e.method===j.CreatePermission?this.permit(e,t,o):this.bindChannel(e,t,o)}async allocate(e,t,n,r){let{auth:i,key:a,username:o}=n;if(r!==void 0){this.fail(e,t,437,`Allocation Mismatch`,[],a);return}let s=P(e,N.RequestedTransport);if(s===void 0||s.length!==4){this.fail(e,t,400,`Bad Request`,[],a);return}if(s[0]!==17){this.fail(e,t,442,`Unsupported Transport Protocol`,[],a);return}let c=P(e,N.RequestedAddressFamily);if(c!==void 0&&c[0]!==1){this.fail(e,t,440,`Address Family not Supported`,[],a);return}if(this.retained!==void 0&&!this.retained.has(i.owner)){this.fail(e,t,403,`Forbidden`,[],a);return}if(this.allocations.size>=this.quotas.totalAllocations){this.fail(e,t,508,`Insufficient Capacity`,[],a);return}if(this.allocationCount(i.owner)>=this.quotas.allocationsPerOwner){this.fail(e,t,486,`Allocation Quota Reached`,[],a);return}let l=await this.relayedSocket();if(l===void 0){this.fail(e,t,508,`Insufficient Capacity`,[],a);return}if(!this.closed&&this.retained!==void 0&&!this.retained.has(i.owner)){l.close(),this.fail(e,t,403,`Forbidden`,[],a);return}if(this.closed||this.allocations.has(R(t))||this.allocationCount(i.owner)>=this.quotas.allocationsPerOwner||this.allocations.size>=this.quotas.totalAllocations){l.close(),this.closed||this.fail(e,t,486,`Allocation Quota Reached`,[],a);return}let u=this.now(),d=this.grantedLifetime(e,u,u),f={key:R(t),client:t,owner:i.owner,username:o,integrityKey:a,transactionId:Buffer.from(e.transactionId),socket:l,relayed:{address:this.relayAddress,port:l.address().port},createdAt:u,expiresAt:u+d*1e3,permissions:new Map,channelsByNumber:new Map,channelsByPeer:new Map,response:Buffer.alloc(0)};l.on(`message`,(e,t)=>this.fromPeer(f,e,t)),l.on(`error`,e=>this.options.onError?.(e)),this.allocations.set(f.key,f),f.response=this.reply(e,t,[{type:N.XorRelayedAddress,value:F(f.relayed,e.transactionId)},{type:N.Lifetime,value:L(d)},{type:N.XorMappedAddress,value:F(t,e.transactionId)}],a)}async relayedSocket(){let e=this.options.relayPorts;if(e===void 0)return At(0,this.bindHost);let t=e.max-e.min+1;for(let n=0;n<Math.min(t,8);n+=1){let t=await At(ue(e.min,e.max+1),this.bindHost);if(t!==void 0)return t}let n=new Set(this.allocationPorts());for(let t=e.min;t<=e.max;t+=1){if(n.has(t))continue;let e=await At(t,this.bindHost);if(e!==void 0)return e}}allocationPorts(){return[...this.allocations.values()].map(e=>e.relayed.port)}isServerItself(e){return e.port===this.socket.address().port&&(Et(e.address)||e.address===this.relayAddress||e.address===this.bindHost||this.bindHost===`0.0.0.0`&&this.ownAddresses.has(e.address))}grantedLifetime(e,t,n){let r=P(e,N.Lifetime),i=r!==void 0&&r.length===4?r.readUInt32BE(0):600,a=Math.floor((t+this.quotas.maxAllocationAgeMs-n)/1e3);return Math.max(0,Math.min(i,this.quotas.maxLifetimeSeconds,a))}refresh(e,t,n){let r=this.now(),i=this.grantedLifetime(e,n.createdAt,r);if(i===0){this.remove(n),this.reply(e,t,[{type:N.Lifetime,value:L(0)}],n.integrityKey);return}n.expiresAt=r+i*1e3,this.reply(e,t,[{type:N.Lifetime,value:L(i)}],n.integrityKey)}peerAddresses(e){let t=[];for(let n of lt(e,N.XorPeerAddress)){let r=dt(n,e.transactionId);if(r===void 0)return;t.push(r)}return t.length>0?t:void 0}permit(e,t,n){let r=n.integrityKey,i=this.peerAddresses(e);if(i===void 0){this.fail(e,t,400,`Bad Request`,[],r);return}if(i.some(e=>!b(e.address))){this.fail(e,t,443,`Peer Address Family Mismatch`,[],r);return}if(i.some(e=>!this.allowPeer(e.address))){this.fail(e,t,403,`Forbidden`,[],r);return}let a=new Set(i.map(e=>e.address).filter(e=>!n.permissions.has(e)));if(n.permissions.size+a.size>this.quotas.permissionsPerAllocation){this.fail(e,t,508,`Insufficient Capacity`,[],r);return}let o=this.now()+Ct;for(let e of i)n.permissions.set(e.address,o);this.reply(e,t,[],r)}bindChannel(e,t,n){let r=n.integrityKey,i=P(e,N.ChannelNumber),a=this.peerAddresses(e),o=i!==void 0&&i.length===4?i.readUInt16BE(0):-1;if(o<16384||o>20479||a===void 0||a.length!==1){this.fail(e,t,400,`Bad Request`,[],r);return}let s=a[0];if(!b(s.address)){this.fail(e,t,443,`Peer Address Family Mismatch`,[],r);return}if(!this.allowPeer(s.address)){this.fail(e,t,403,`Forbidden`,[],r);return}let c=n.channelsByNumber.get(o),l=n.channelsByPeer.get(R(s));if(c!==void 0&&R(c.peer)!==R(s)||l!==void 0&&l.number!==o){this.fail(e,t,400,`Bad Request`,[],r);return}if(c===void 0&&n.channelsByNumber.size>=this.quotas.channelsPerAllocation||!n.permissions.has(s.address)&&n.permissions.size>=this.quotas.permissionsPerAllocation){this.fail(e,t,508,`Insufficient Capacity`,[],r);return}let u=this.now(),d=c??{number:o,peer:s,expiresAt:0};d.expiresAt=u+6e5,n.channelsByNumber.set(o,d),n.channelsByPeer.set(R(s),d),n.permissions.set(s.address,u+Ct),this.reply(e,t,[],r)}permitted(e,t){let n=e.permissions.get(t);return n!==void 0&&n>this.now()}spend(e,t){let n=this.now(),r=this.quotas.bytesPerSecondPerOwner,i=this.buckets.get(e)??{tokens:r,at:n};return this.buckets.set(e,i),z(i,r,n,t)?(i.tokens-=t,!0):!1}live(e){return e===void 0?!1:e.expiresAt>this.now()?!0:(this.remove(e),!1)}fromClientSend(e,t){let n=this.allocations.get(R(t));if(!this.live(n))return;let r=P(e,N.XorPeerAddress),i=P(e,N.Data);if(r===void 0||i===void 0)return;let a=dt(r,e.transactionId);a===void 0||!this.permitted(n,a.address)||this.isServerItself(a)||this.spend(n.owner,i.length)&&n.socket.send(i,a.port,a.address)}fromClientChannel(e,t){let n=this.allocations.get(R(t));if(!this.live(n))return;let r=yt(e);if(r===void 0)return;let i=n.channelsByNumber.get(r.channel);i===void 0||i.expiresAt<=this.now()||this.permitted(n,i.peer.address)&&(this.isServerItself(i.peer)||this.spend(n.owner,r.payload.length)&&n.socket.send(r.payload,i.peer.port,i.peer.address))}fromPeer(e,t,n){if(this.allocations.get(e.key)!==e||!this.live(e)||!this.permitted(e,n.address)||!this.spend(e.owner,t.length))return;let r=e.channelsByPeer.get(R(n));if(r!==void 0&&r.expiresAt>this.now()){this.send(bt(r.number,t),e.client);return}let i=le(12);this.send(I(j.Data,M.Indication,i,[{type:N.XorPeerAddress,value:F({address:n.address,port:n.port},i)},{type:N.Data,value:t}]),e.client)}remove(e){this.allocations.get(e.key)===e&&this.allocations.delete(e.key);try{e.socket.close()}catch{}}sweep(){let e=this.now();for(let[t,n]of this.answerBuckets)Math.abs(e-n.at)>=1e3&&this.answerBuckets.delete(t);for(let t of[...this.allocations.values()]){if(t.expiresAt<=e){this.remove(t);continue}for(let[n,r]of t.permissions)r<=e&&t.permissions.delete(n);for(let[n,r]of t.channelsByNumber)r.expiresAt>e||(t.channelsByNumber.delete(n),t.channelsByPeer.delete(R(r.peer)))}}};const Ft=600*1e3,It=3600*1e3,Lt=/^(\d{1,12}):([A-Za-z0-9_-]{22})$/;function Rt(e){return Buffer.from(e).toString(`base64url`)}async function zt(e,t,n=Ft){let r=Math.min(Math.max(n,1e3),It),i=(await e.tag(`relay-user`,`outbound`,h(t))).slice(0,16),a=`${Math.floor((t+r)/1e3)}:${Rt(i)}`;return{username:a,credential:await e.relayPassword(`outbound`,a)}}function Bt(e){return`turn:${e.host.includes(`:`)?`[${e.host}]`:e.host}:${e.port}?transport=udp`}async function Vt(e,t,n,r){if(t.length===0)return[];let{username:i,credential:a}=await zt(e,n,r);return t.map(e=>({urls:Bt(e),username:i,credential:a}))}var B=class extends Error{deviceId;need;constructor(e,t,n){let r=t===`relay-only`?`only relayed connections are allowed`:`no direct path was found (${n?.cause instanceof Error?n.cause.message:String(n?.cause)})`;super(`a relay device is needed to reach device ${e}: ${r}, and no paired device advertises a relay and no TURN server is configured. Run the relay on an always-on device, or configure a TURN server.`,n?.cause===void 0?void 0:{cause:n.cause}),this.name=`MeshRelayNeededError`,this.deviceId=e,this.need=t}},Ht=class e{server;now;peers=[];owners;constructor(e,t){this.server=e,this.now=t}static async start(t={}){let n=t.now??Date.now,r,i=await Pt.start({...t.host===void 0?{}:{host:t.host},...t.port===void 0?{}:{port:t.port},...t.relayAddress===void 0?{}:{relayAddress:t.relayAddress},...t.relayPorts===void 0?{}:{relayPorts:t.relayPorts},...t.quotas===void 0?{}:{quotas:t.quotas},...t.allowPeer===void 0?{}:{allowPeer:t.allowPeer},...t.allowPrivatePeers===void 0?{}:{allowPrivatePeers:t.allowPrivatePeers},...t.onError===void 0?{}:{onError:t.onError},now:n,authorize:e=>r===void 0?Promise.resolve(void 0):r.authorize(e)});return r=new e(i,n),r}get endpoint(){let{address:e,port:t}=this.server.address;return{host:e,port:t}}allocationCount(e){return this.server.allocationCount(e)}declarePeers(e){this.peers=[...e],this.server.retain(new Set(e.map(e=>e.deviceId)))}async authorize(e){let t=Lt.exec(e);if(t===null)return;let n=this.now(),r=Number(t[1])*1e3;if(r<=n||r-n>366e4)return;let i=(await this.tagOwners(h(n))).get(t[2]);if(!(i===void 0||!this.peers.some(e=>e.deviceId===i.deviceId)))return{owner:i.deviceId,password:await i.rendezvous.relayPassword(`inbound`,e)}}tagOwners(e){let t=this.owners;if(t!==void 0&&t.epoch===e&&t.peers===this.peers)return t.byTag;let n=this.peers,r=(async()=>{let t=new Map;for(let r of n)for(let n of await r.rendezvous.lookupTags(`relay-user`,e))t.set(Rt(n.slice(0,16)),r);return t})();return r.catch(()=>{this.owners?.byTag===r&&(this.owners=void 0)}),this.owners={epoch:e,peers:n,byTag:r},r}close(){return this.peers=[],this.server.close()}};const Ut=2e4,Wt=1e3,Gt=3e3,Kt=`mesh-lists`,qt=`{"t":"${Kt}"`;function Jt(e){return{send:t=>e.send(t),onFrame:t=>e.onMessage(t),onClose:t=>e.readyState===`closed`?(queueMicrotask(t),()=>void 0):e.onStateChange(e=>{e===`closed`&&t()}),close:()=>e.close()}}var Yt=class{last;waiting;timer;run(e){let t=Date.now();if(this.last===void 0||t-this.last>=Wt){this.last=t,e();return}this.waiting=e,this.timer===void 0&&(this.timer=setTimeout(()=>{this.timer=void 0;let e=this.waiting;this.waiting=void 0,e!==void 0&&this.run(e)},Wt-(t-this.last)),this.timer.unref?.())}cancel(){this.timer!==void 0&&clearTimeout(this.timer),this.timer=void 0,this.waiting=void 0}};function Xt(){let e=new Uint8Array(16);return globalThis.crypto.getRandomValues(e),Buffer.from(e).toString(`base64url`)}function V(e,t){return t!==void 0&&t.seq>e.seq&&t.signingKeyId===e.signingKeyId}function H(e,t){return e===void 0?t:t===void 0?e:Math.max(e,t)}function Zt(e,t){let n=new Map;for(let r of[e.bySigningKey??{},t.bySigningKey??{}])for(let[e,t]of Object.entries(r)){let r=n.get(e)??{},i=H(r.rosterSeq,t.rosterSeq),a=H(r.revocationSeq,t.revocationSeq);n.set(e,{...i===void 0?{}:{rosterSeq:i},...a===void 0?{}:{revocationSeq:a}})}let r=Object.fromEntries(n),i=H(e.signingKeyRevocationSeq,t.signingKeyRevocationSeq);return{...i===void 0?{}:{signingKeyRevocationSeq:i},bySigningKey:r}}function Qt(e,t){let n=t.signingKeyCertificate.signingKeyId===e.signingKeyCertificate.signingKeyId;return{...t,...n&&V(t.roster,e.roster)?{roster:e.roster}:{},...n&&V(t.revocation,e.revocation)?{revocation:e.revocation}:{},...e.signingKeyRevocation.seq>t.signingKeyRevocation.seq?{signingKeyRevocation:e.signingKeyRevocation}:{},marks:Zt(e.marks,t.marks)}}function $t(e,t){return t.signingKeyCertificate.signingKeyId===e.signingKeyCertificate.signingKeyId?t.roster.seq>e.roster.seq||t.revocation.seq>e.revocation.seq||t.signingKeyRevocation.seq>e.signingKeyRevocation.seq:!1}function en(e){if(e.startsWith(qt))try{let t=JSON.parse(e);return typeof t==`object`&&t&&!Array.isArray(t)?t:void 0}catch{return{}}}var tn=class{options;instance=Xt();identity;sessionDescriptor;peers=new Map;byInbound=new Map;linkHandlers=new Set;refusalHandlers=new Set;waiters=new Set;unsubscribes=[];started=!1;stopped=!1;sync=Promise.resolve();constructor(e){this.options=e,this.identity=e.identity,this.sessionDescriptor=e.sessionDescriptor}get deviceId(){return this.identity.deviceCertificate.deviceId}async start(){if(this.started)throw Error(`DeviceMeshNode already started`);this.started=!0,this.unsubscribes.push(this.options.relay.onMessage((e,t)=>this.receive(e,t))),await this.syncPeers()}refresh(e){if(e.sessionDescriptor!==void 0&&(this.sessionDescriptor=e.sessionDescriptor),e.identity===void 0)return Promise.resolve();let t=this.identity;this.identity=Qt(t,e.identity);let n=this.syncPeers();return $t(t,this.identity)&&n.then(()=>this.pushLists(),()=>void 0),n}pushLists(){if(this.stopped)return;let{roster:e,revocation:t,signingKeyRevocation:n}=this.identity,r=JSON.stringify({t:Kt,roster:e,revocation:t,signingKeyRevocation:n});for(let e of this.peers.values())try{e.admitted?.exposed?.send(r)}catch{}}async receiveLists(e){let t=this.identity,n=s(this.options.cryptoContext,e.roster),r=o(this.options.cryptoContext,e.revocation),i=d(this.options.cryptoContext,e.signingKeyRevocation),a={...n.ok&&V(t.roster,n.value)?{roster:n.value}:{},...r.ok&&V(t.revocation,r.value)?{revocation:r.value}:{},...i.ok&&i.value.seq>t.signingKeyRevocation.seq?{signingKeyRevocation:i.value}:{}};if(Object.keys(a).length===0)return;let c=await ae(this.options.cryptoContext,{masterPublicKey:t.masterPublicKey,signingKeyCert:t.signingKeyCertificate,deviceCert:t.deviceCertificate,roster:a.roster??t.roster,revocation:a.revocation??t.revocation,signingKeyRevocation:a.signingKeyRevocation??t.signingKeyRevocation,now:(this.options.now??Date.now)(),lastSeen:t.marks,required:{roster:!0,revocation:!0,signingKeyRevocation:!0},listExpiryGraceMs:1/0});if(!c.ok||this.stopped)return;let{rosterSeq:l,revocationSeq:u,signingKeyRevocationSeq:f}=c.accepted;this.adoptLists({...a,marks:{...a.signingKeyRevocation!==void 0&&f!==void 0?{signingKeyRevocationSeq:f}:{},bySigningKey:{[c.signingKeyId]:{...a.roster!==void 0&&l!==void 0?{rosterSeq:l}:{},...a.revocation!==void 0&&u!==void 0?{revocationSeq:u}:{}}}}})}syncPeers(){this.sync=this.sync.then(async()=>{if(this.stopped)return;let e=this.identity,t=e.deviceCertificate,n=new Set(e.revocation.revokedDeviceIds),r=new Map;for(let i of e.roster.devices)i.deviceId!==t.deviceId&&!n.has(i.deviceId)&&r.set(i.deviceId,i);for(let[e,t]of this.peers){let n=r.get(e);(n===void 0||n.kaKey!==t.device.kaKey||n.kaEpoch!==t.device.kaEpoch)&&this.drop(t)}let i=[];for(let[n,a]of r){if(this.peers.has(n))continue;let r,o;try{r=await ee(this.options.cryptoContext,{ownKaPrivateKey:e.kaPrivateKey,own:t,peerDeviceId:n,lists:e}),o=await r.relayInbox()}catch{continue}let s={device:a,role:t.deviceId<a.deviceId?`offerer`:`answerer`,rendezvous:r,inbound:o.inbound,outbound:o.outbound,attempts:new Yt,replies:new Yt,relayFailures:0};this.peers.set(n,s),this.byInbound.set(o.inbound,s),i.push(s)}if(this.stopped)return;this.options.relayServer?.declarePeers([...this.peers.values()].map(e=>({deviceId:e.device.deviceId,rendezvous:e.rendezvous}))),this.options.relay.declarePresence([...this.byInbound.keys()]);let a=this.peerRoutes();this.options.relay.declarePeers?.(a),this.options.relays?.advertised?.(a,AbortSignal.timeout(Gt)).catch(()=>void 0);for(let e of i)this.hello(e)});let e=this.sync;return this.sync=e.catch(()=>void 0),e}drop(e){this.peers.delete(e.device.deviceId),this.byInbound.delete(e.inbound),e.attempts.cancel(),e.replies.cancel();let{pending:t,admitted:n}=e;if(e.pending=void 0,e.admitted=void 0,t?.link.close(),n?.link.close(),t!==void 0&&!this.stopped){let t={deviceId:e.device.deviceId,end:`closed`,error:Error(`peer device was revoked or is no longer in the roster`)};for(let e of this.refusalHandlers)e(t)}}roleFor(e){return this.peers.get(e)?.role}link(e){return this.peers.get(e)?.admitted?.exposed}connect(e,t=Ut){if(this.stopped)return Promise.reject(Error(`device mesh node stopped`));let n=this.peers.get(e);if(n===void 0)return Promise.reject(Error(`not a rostered, unrevoked peer device`));let r=n.admitted?.exposed;return r===void 0?new Promise((r,i)=>{let a=()=>{clearTimeout(s),c(),l(),this.waiters.delete(o)},o=e=>{a(),i(e)},s=setTimeout(()=>o(Error(`peer device did not connect in time`)),t);s.unref?.();let c=this.onLink(t=>{t.admission.deviceId===e&&(a(),r(t))}),l=this.onRefusal(t=>{t.deviceId===e&&o(t.error instanceof Error?t.error:Error(`connection ${t.end}`))});this.waiters.add(o),this.hello(n)}):Promise.resolve(r)}onLink(e){return this.linkHandlers.add(e),()=>this.linkHandlers.delete(e)}onRefusal(e){return this.refusalHandlers.add(e),()=>this.refusalHandlers.delete(e)}stop(){if(!this.stopped){this.stopped=!0;for(let e of this.unsubscribes.splice(0))e();for(let e of[...this.peers.values()])this.drop(e);for(let e of[...this.waiters])e(Error(`device mesh node stopped`));this.linkHandlers.clear(),this.refusalHandlers.clear()}}hello(e){this.stopped||this.options.relay.send(e.outbound,{v:1,kind:`hello`,from:this.instance})}receive(e,t){if(this.stopped)return;let n=this.byInbound.get(e);if(n===void 0)return;let r=et(t);if(r===void 0)return;if(r.kind===`hello`){this.onHello(n,r.from);return}if(r.to!==this.instance)return;if(r.kind===`offer`){this.onOffer(n,r);return}for(let e of[n.pending,n.admitted])if(e?.cid===r.cid&&e.remoteInstance===r.from){e.link.onSignal(U(r));return}let i=n.waitingOffer;r.kind===`ice`&&i?.cid===r.cid&&i.from===r.from&&i.ice.length<64&&i.ice.push(U(r))}serves(e,t){return e.admitted?.remoteInstance===t||e.pending?.remoteInstance===t}onHello(e,t){if(!this.serves(e,t)){if(e.role===`answerer`){e.replies.run(()=>this.hello(e));return}e.attempts.run(()=>{this.stopped||this.peers.get(e.device.deviceId)!==e||this.serves(e,t)||this.startAttempt(e,t,Xt()).link.offer()})}}onOffer(e,t){if(e.role!==`answerer`||e.admitted?.cid===t.cid||e.pending?.cid===t.cid)return;let n={cid:t.cid,from:t.from,ice:[]};e.waitingOffer=n,e.attempts.run(()=>{if(e.waitingOffer===n&&(e.waitingOffer=void 0),this.stopped||this.peers.get(e.device.deviceId)!==e||e.admitted?.cid===t.cid||e.pending?.cid===t.cid)return;let{link:r}=this.startAttempt(e,t.from,t.cid);r.onSignal(U(t));for(let e of n.ice)r.onSignal(e)})}startAttempt(e,t,n){let r=e.pending;e.pending=void 0,r?.link.close();let i=r=>{this.stopped||this.options.relay.send(e.outbound,{v:1,from:this.instance,to:t,cid:n,...r})},a,o=new at({role:e.role,createPeer:async()=>{let{stage:t,servers:n}=await this.relayStage(e);return a!==void 0&&(a.relayStage=t),this.createPeer(n)},sendSignal:i,startHandshake:t=>ne(this.options.cryptoContext,{role:e.role===`offerer`?`initiator`:`responder`,identity:this.identity,sessionDescriptor:this.sessionDescriptor,...e.role===`offerer`?{expectedPeerDeviceId:e.device.deviceId}:{},localFingerprint:t.localFingerprint,remoteFingerprint:t.remoteFingerprint,locality:`another-host`,localPolicy:this.options.localPolicy,send:t.send,...this.options.fetchLatestLists===void 0?{}:{fetchLatestLists:this.options.fetchLatestLists},onListsAdopted:e=>this.adoptLists(e),...this.options.now===void 0?{}:{now:this.options.now},...this.options.handshakeTimeoutMs===void 0?{}:{timeoutMs:this.options.handshakeTimeoutMs}}),connectTimeoutMs:this.options.connectTimeoutMs??Ut,accepts:t=>t.admission.deviceId===e.device.deviceId,onAdmitted:t=>this.admitted(e,o,t),onEnded:(t,n)=>this.ended(e,o,t,n)});return a={cid:n,remoteInstance:t,link:o},e.pending=a,a}adoptLists(e){let t=this.identity,n={...t,...V(t.roster,e.roster)?{roster:e.roster}:{},...V(t.revocation,e.revocation)?{revocation:e.revocation}:{},...e.signingKeyRevocation!==void 0&&e.signingKeyRevocation.seq>t.signingKeyRevocation.seq?{signingKeyRevocation:e.signingKeyRevocation}:{},marks:Zt(t.marks,e.marks)};this.refresh({identity:n}).catch(()=>void 0),this.options.onListsAdopted?.(e)}admitted(e,t,n){let r=e.pending;if(r===void 0||r.link!==t)return;if(n.admission.deviceId!==e.device.deviceId){t.close();return}let i=n.admission,a=t.channelBinding;if(a===void 0){t.close();return}let o=new se({deviceId:i.deviceId,sessionId:i.sessionId,locality:i.locality,capabilities:i.capabilities},this.options.operatorApprover);t.onEnd(()=>o.close());let s=o.authorize(`message`);t.onMessage(e=>{let t=en(e);t!==void 0&&this.receiveLists(t).catch(()=>void 0)});let c={admission:i,result:n,channelBinding:a,authority:o,send:e=>t.send(e),onMessage:e=>t.onMessage(n=>{en(n)===void 0&&s.then(r=>{r.allowed&&!t.ended?e(n):t.close()})}),openFileChannel:async()=>Jt(await t.openFileChannel()),onFileChannel:e=>t.onFileChannel(t=>e(Jt(t))),onClose:e=>t.onEnd(()=>e()),close:()=>t.close()};r.exposed=c,e.relayFailures=0;let l=e.admitted;e.admitted=r,e.pending=void 0,l?.link.close(),this.options.relay.confirmPeer?.(i.deviceId);for(let e of this.linkHandlers)e(c)}ended(e,t,n,r){if(e.admitted?.link===t){e.admitted=void 0;return}if(e.pending?.link!==t)return;let i=e.pending.relayStage;e.pending=void 0;let a=r.stage===`connecting`&&(n===`timeout`||r.peer?.state===`failed`)&&r.peer?.history.includes(`connected`)!==!0,o=r;r.cause instanceof B?o=r.cause:a&&i===`direct`?o=new B(e.device.deviceId,`no-direct-path`,{cause:r}):a&&(e.relayFailures+=1);let s={deviceId:e.device.deviceId,end:n,error:o};for(let e of this.refusalHandlers)e(s)}async relayStage(e){let t=this.options.relays,n=[],r=await this.embeddedRelays(e);if(r.length>0&&n.push({stage:`embedded`,servers:r}),t?.configured!==void 0&&t.configured.length>0&&n.push({stage:`configured`,servers:t.configured}),n.length===0){if(t?.relayOnly===!0)throw new B(e.device.deviceId,`relay-only`);return{stage:`direct`,servers:[]}}return n[e.relayFailures%n.length]}peerRoutes(e){let t=[...this.peers.values()];return(e===void 0?t:[e,...t.filter(t=>t!==e)]).map(e=>({deviceId:e.device.deviceId,inbound:e.inbound,outbound:e.outbound,rendezvous:e.rendezvous}))}async embeddedRelays(e){let t=this.options.relays?.advertised;if(t===void 0)return[];let n;try{n=await t(this.peerRoutes(e),AbortSignal.timeout(Gt))}catch{return[]}let r=e.device.deviceId,i=[r,...[...n.keys()].filter(e=>e!==r)],a=(this.options.now??Date.now)(),o=[],s=0;for(let e of i){if(s>=2)break;let t=n.get(e),r=this.peers.get(e);t!==void 0&&t.length!==0&&r!==void 0&&(s+=1,o.push(...await Vt(r.rendezvous,t.slice(0,3),a,this.options.relays?.credentialTtlMs)))}return o}createPeer(e){let t=[...this.options.iceServers??[],...e];return new T({...t.length>0?{iceServers:t}:{},...this.options.relays?.relayOnly===!0?{forceTurn:!0}:{},...this.options.loadDataChannel===void 0?{}:{loadDataChannel:this.options.loadDataChannel}})}};function U(e){return e.kind===`ice`?{kind:`ice`,candidate:{...e.candidate}}:{kind:e.kind,sdp:e.sdp}}function nn(){let e=new Map;return{connect(){let t={messages:new Set,absents:new Set,topics:new Set,open:!0},n=()=>{for(let n of t.topics)e.get(n)===t&&e.delete(n);t.topics=new Set};return{declarePresence(r){if(t.open){n(),t.topics=new Set(r);for(let n of r)e.set(n,t)}},send(n,r){if(!t.open)return;let i=JSON.parse(JSON.stringify(r));queueMicrotask(()=>{let r=e.get(n);if(r===void 0||r===t||!r.open){for(let e of t.absents)e(n);return}for(let e of r.messages)e(n,i)})},onMessage(e){return t.messages.add(e),()=>t.messages.delete(e)},onAbsent(e){return t.absents.add(e),()=>t.absents.delete(e)},close(){t.open=!1,n(),t.messages.clear(),t.absents.clear()}}}}}var rn=class{options;socket;messages=new Set;absents=new Set;outbox=[];topics;closed=!1;constructor(e){this.options=e;let t=e.createSocket??(e=>new g(e));this.socket=t(e.url),this.socket.on(`open`,()=>this.flush()),this.socket.on(`message`,e=>this.receive(e)),this.socket.on(`error`,e=>this.options.onError?.(e instanceof Error?e:Error(String(e)))),this.socket.on(`close`,()=>{this.closed||this.options.onError?.(Error(`signaling relay connection closed`))})}flush(){this.topics!==void 0&&this.write({type:`presence`,topics:this.topics});for(let e of this.outbox.splice(0))this.socket.send(e)}write(e){this.socket.send(JSON.stringify(e))}receive(e){let t;try{t=JSON.parse(typeof e==`string`?e:String(e))}catch{return}if(typeof t!=`object`||!t)return;let n=t;if(n.type===`message`&&typeof n.topic==`string`)for(let e of this.messages)e(n.topic,n.data);else if(n.type===`absent`&&typeof n.topic==`string`)for(let e of this.absents)e(n.topic);else n.type===`present`?this.options.onPresent?.():n.type===`error`&&this.options.onError?.(Error(`signaling relay refused a frame: ${String(n.reason)}`))}declarePresence(e){this.closed||(this.topics=[...e],this.socket.readyState===1&&this.write({type:`presence`,topics:this.topics}))}send(e,t){if(this.closed)return;let n=JSON.stringify({type:`message`,topic:e,data:t});this.socket.readyState===1?this.socket.send(n):this.outbox.length<256?this.outbox.push(n):this.options.onError?.(Error(`signaling relay is not reachable; message dropped`))}onMessage(e){return this.messages.add(e),()=>this.messages.delete(e)}onAbsent(e){return this.absents.add(e),()=>this.absents.delete(e)}close(){this.closed=!0,this.messages.clear(),this.absents.clear(),this.outbox.length=0,this.socket.close()}};const an=3;function on(e){return{candidates:t=>Promise.resolve(e.recall(t.deviceId))}}function sn(e,t){return e.host===t.host&&e.port===t.port}function cn(e,t){return[{host:t.host,port:t.port},...e.filter(e=>!sn(e,t))].slice(0,3)}function ln(){let e=new Map,t;return{recall:t=>e.get(t)??[],remember:(t,n)=>{e.set(t,cn(e.get(t)??[],n))},retain:t=>{let n=new Set(t);for(let t of[...e.keys()])n.has(t)||e.delete(t)},lastListenPort:()=>t,rememberListenPort:e=>{t=e}}}const un=/^[A-Za-z0-9_-]{43}$/,dn=/^[A-Za-z0-9_-]{22}$/,fn=12e4,pn=1008;function W(e){return _(`sha256`).update(`lan-address:${e}`).digest(`base64url`)}function mn(e,t){return v(`sha256`,e).update(`lan-present:${t}`).digest(`base64url`)}function hn(e,t,n){if(typeof n!=`string`)return!1;let r=Buffer.from(mn(e,t)),i=Buffer.from(n);return i.length===r.length&&y(i,r)}function gn(e,t){return new Promise((n,r)=>{let i=new oe({port:e,...t===void 0?{}:{host:t},maxPayload:65536,perMessageDeflate:!1,verifyClient:e=>e.origin===void 0||e.origin===``}),a=e=>{i.close(),r(e)};i.once(`error`,a),i.once(`listening`,()=>{i.off(`error`,a),n(i)})})}function _n(e){let t;try{t=JSON.parse(String(e))}catch{return}if(typeof t!=`object`||!t||Array.isArray(t))return;let n=t;if(!(typeof n.type!=`string`||typeof n.to!=`string`||!un.test(n.to)))return n.type===`probe`?typeof n.nonce==`string`&&dn.test(n.nonce)?{type:n.type,to:n.to,nonce:n.nonce}:void 0:{type:n.type,to:n.to,data:n.data}}async function vn(e={}){let t;try{t=await gn(e.port??0,e.host)}catch(n){if(e.port===void 0||e.port===0)throw n;t=await gn(0,e.host)}let n=t.address(),r=typeof n==`object`&&n?n.port:0,i=new Map,a=new Set;return t.on(`connection`,e=>{if(t.clients.size>32){e.close(pn);return}let n=0,r=Date.now(),o=setTimeout(()=>e.close(),fn);o.unref?.(),e.on(`close`,()=>clearTimeout(o)),e.on(`error`,()=>e.close()),e.on(`message`,t=>{let s=Date.now();if(s-r>1e4&&(r=s,n=0),n+=1,n>128){e.close(pn);return}clearTimeout(o),o=setTimeout(()=>e.close(),fn),o.unref?.();let c=_n(t);if(c===void 0)return;let l=i.get(c.to);if(l===void 0){e.send(JSON.stringify({type:`absent`,to:c.to}));return}if(c.type===`probe`&&c.nonce!==void 0){e.send(JSON.stringify({type:`present`,to:c.to,nonce:c.nonce,proof:mn(l,c.nonce)}));return}if(c.type===`message`)for(let e of a)e(l,c.data)})}),{port:r,setPresence(e){i=new Map(e.map(e=>[W(e),e]))},onMessage(e){return a.add(e),()=>a.delete(e)},close(){a.clear(),i=new Map;for(let e of t.clients)e.terminate();return new Promise(e=>t.close(()=>e()))}}}const G=`_rdv._tcp.local`;function yn(){return e(import.meta.url)(`multicast-dns`)()}function bn(){let e=[];for(let t of Object.values(x()))for(let n of t??[])n.internal||(n.family===`IPv4`||n.family===`IPv6`&&!n.address.startsWith(`fe80`))&&e.push(n.address);return e}function xn(e){let t=new Uint8Array(e);return globalThis.crypto.getRandomValues(t),Buffer.from(t).toString(`hex`)}function Sn(e){return Buffer.from(e.subarray(0,16)).toString(`hex`)}function Cn(e){return Math.max(8,Math.ceil(e/8)*8)}function K(e,t){return e.toLowerCase()===t.toLowerCase()}var wn=class{options;transport;routes=[];port;records;instances=new Set;timer;generation=0;closed=!1;epochCover;announced;lastAnswer;answerTimer;constructor(e={}){this.options=e}now(){return(this.options.now??Date.now)()}open(){if(!this.closed){if(this.transport!==void 0)return this.transport;try{let e=(this.options.createTransport??yn)();return e.on(`query`,e=>this.onQuery(e)),e.on(`error`,e=>this.options.onError?.(e)),this.transport=e,e}catch(e){this.closed=!0,this.options.onError?.(e instanceof Error?e:Error(String(e)));return}}}advertise(e,t){return this.routes=e,this.port=t,this.rebuild()}async rebuild(){let e=++this.generation,t=this.port;if(this.closed||t===void 0)return;let n=h(this.now()),r=await Promise.all(this.routes.map(e=>e.rendezvous.tag(`mdns`,`outbound`,n)));if(e!==this.generation||this.closed)return;this.epochCover?.epoch!==n&&(this.epochCover={epoch:n,padding:[],target:`${xn(8)}.local`});let{padding:i,target:a}=this.epochCover,o=Cn(r.length)-r.length;for(;i.length<o;)i.push(xn(16));let s=[...r.map(Sn),...i.slice(0,o)].sort(),c=JSON.stringify([n,t,s]),l=s.map(e=>({name:G,type:`PTR`,ttl:120,data:`${e}.${G}`})),u=[];for(let e of s){let n=`${e}.${G}`;u.push({name:n,type:`SRV`,ttl:120,data:{priority:0,weight:0,port:t,target:a}},{name:n,type:`TXT`,ttl:120,data:[]})}for(let e of(this.options.addresses??bn)())u.push({name:a,type:e.includes(`:`)?`AAAA`:`A`,ttl:120,data:e});this.records={answers:l,additionals:u},this.instances=new Set(s.map(e=>`${e}.${G}`.toLowerCase())),this.schedule(n),c!==this.announced&&(this.announced=c,this.open()?.respond(this.records))}schedule(e){this.timer!==void 0&&clearTimeout(this.timer);let t=Math.max(0,(e+1)*a-this.now());this.timer=setTimeout(()=>{this.rebuild().catch(()=>void 0)},t),this.timer.unref?.()}onQuery(e){this.records===void 0||this.closed||(e.questions??[]).some(e=>K(e.name,`_rdv._tcp.local`)&&(e.type===`PTR`||e.type===`ANY`)||this.instances.has(e.name.toLowerCase()))&&this.answer()}answer(){if(this.answerTimer!==void 0)return;let e=this.options.minAnswerIntervalMs??500,t=this.lastAnswer===void 0?0:this.lastAnswer+e-this.now(),n=()=>{this.answerTimer=void 0,!(this.closed||this.records===void 0)&&(this.lastAnswer=this.now(),this.transport?.respond(this.records))};if(t<=0){n();return}this.answerTimer=setTimeout(n,t),this.answerTimer.unref?.()}async candidates(e,t){let n=this.open();if(n===void 0||t.aborted)return[];let r=h(this.now()),i=new Set((await e.rendezvous.lookupTags(`mdns`,r)).map(e=>`${Sn(e)}.${G}`));return t.aborted||this.closed?[]:new Promise(e=>{let r=[],a,o=()=>{clearTimeout(c),clearTimeout(a),t.removeEventListener(`abort`,o),n.removeListener(`response`,s),e(r)},s=(e,t)=>{let n=[...e.answers??[],...e.additionals??[]];for(let e of n){if(e.type!==`PTR`||!K(e.name,`_rdv._tcp.local`)||typeof e.data!=`string`||!i.has(e.data.toLowerCase()))continue;let a=n.find(t=>t.type===`SRV`&&K(t.name,e.data))?.data?.port;if(typeof a!=`number`||!Number.isInteger(a)||a<=0||a>65535)continue;let o=r.filter(e=>e.host===t.address);r.length<8&&o.length<2&&!o.some(e=>e.port===a)&&r.push({host:t.address,port:a})}r.length!==0&&a===void 0&&(a=setTimeout(o,this.options.answerGraceMs??200),a.unref?.())},c=setTimeout(o,this.options.lookupTimeoutMs??1e3);c.unref?.(),t.addEventListener(`abort`,o,{once:!0}),n.on(`response`,s),n.query({questions:[{name:G,type:`PTR`}]})})}close(){this.closed=!0,this.generation+=1,this.timer!==void 0&&clearTimeout(this.timer),this.answerTimer!==void 0&&clearTimeout(this.answerTimer),this.transport?.destroy(),this.transport=void 0}};function Tn(){let e=new Set,t=[],n=(t,n,r)=>{let i=JSON.parse(JSON.stringify(n));queueMicrotask(()=>{for(let n of e)for(let e of r(n))e(i,{address:t.address})})};return{responses:t,transport(r){let i={address:r,queries:new Set,responses:new Set};return e.add(i),{on(e,t){e===`query`&&i.queries.add(t),e===`response`&&i.responses.add(t)},removeListener(e,t){i.responses.delete(t)},query(e){n(i,e,e=>e.queries)},respond(e){t.push(JSON.parse(JSON.stringify(e))),n(i,e,e=>e.responses)},destroy(){e.delete(i)}}}}}var En=class{until=new Map;failures=new Map;has(e,t){let n=this.until.get(e);return n===void 0?!1:n>t?!0:(this.until.delete(e),!1)}fail(e,t,n){let r=(this.failures.get(e)??0)+1;this.failures.delete(e),this.failures.set(e,r);for(let e of this.failures.keys()){if(this.failures.size<=32)break;this.failures.delete(e),this.until.delete(e)}let i=Math.min(2**(r-1),16);this.until.set(e,t+n*i)}clear(){this.until.clear(),this.failures.clear()}};function Dn(e){if(typeof e!=`object`||!e)return!1;let t=e.kind;return t===`hello`||t===`offer`||t===`answer`}function On(e){return`${e.host}:${e.port}`}function kn(){let e=new Uint8Array(16);return globalThis.crypto.getRandomValues(e),Buffer.from(e).toString(`base64url`)}function An(e){return Buffer.from(e).toString(`base64url`)}function jn(e){return`ws://${e.host.includes(`:`)?`[${e.host}]`:e.host}:${e.port}`}function Mn(e){try{let t=JSON.parse(String(e));return typeof t==`object`&&t?t:void 0}catch{return}}var Nn=class{options;routes=new Map;byDevice=new Map;lanIn=new Map;messages=new Set;absents=new Set;unsubscribes=[];abort=new AbortController;sync=Promise.resolve();pendingPeers=0;waiting=[];timer;closed=!1;constructor(e){this.options=e;for(let e of this.carriers())this.unsubscribes.push(e.onMessage((e,t)=>this.deliver(e,t)),e.onAbsent(e=>this.absent(e)));this.unsubscribes.push(e.listener.onMessage((e,t)=>{let n=this.lanIn.get(e);n!==void 0&&this.deliver(n,t)}))}now(){return(this.options.now??Date.now)()}carriers(){return[...this.options.signaling??[],...this.options.relay===void 0?[]:[this.options.relay]]}deliver(e,t){if(!this.closed)for(let n of this.messages)n(e,t)}absent(e){if(!this.closed)for(let t of this.absents)t(e)}declarePresence(e){for(let t of this.carriers())t.declarePresence(e)}declarePeers(e){for(let t of this.carriers())t.declarePeers?.(e);this.pendingPeers+=1,this.sync=this.sync.then(()=>this.applyPeers(e)).catch(e=>{this.options.onError?.(e instanceof Error?e:Error(String(e)))}).finally(()=>{if(--this.pendingPeers,!(this.pendingPeers>0))for(let{topic:e,data:t}of this.waiting.splice(0))this.send(e,t)})}async applyPeers(e){if(this.closed)return;let t=h(this.now()),n=new Map,r=new Map;for(let i of e){let e=An(await i.rendezvous.tag(`lan-inbox`,`outbound`,t));for(let e of await i.rendezvous.lookupTags(`lan-inbox`,t))n.set(An(e),i.inbound);let a=this.routes.get(i.outbound),o=a!==void 0&&a.route.deviceId===i.deviceId?a:{route:i,lanOut:e,path:{kind:`unresolved`},avoid:new En,avoidCarriers:new En};o.route=i,o.lanOut=e,r.set(i.outbound,o)}if(!this.closed){for(let[e,t]of this.routes)r.get(e)!==t&&this.reset(t);this.routes.clear(),this.byDevice.clear();for(let[e,t]of r)this.routes.set(e,t),this.byDevice.set(t.route.deviceId,t);this.lanIn=n,this.options.listener.setPresence([...n.keys()]),this.cacheWrite(()=>this.options.cache?.retain(e.map(e=>e.deviceId))),await Promise.all((this.options.advertisers??[]).map(t=>t.advertise(e,this.options.listener.port))),!this.closed&&this.scheduleEpoch(t,e)}}scheduleEpoch(e,t){this.timer!==void 0&&clearTimeout(this.timer);let n=Math.max(0,(e+1)*a-this.now());this.timer=setTimeout(()=>this.declarePeers(t),n),this.timer.unref?.()}confirmPeer(e){let t=this.byDevice.get(e),n=t?.path;if(!(t===void 0||n?.kind!==`direct`&&n?.kind!==`relay`)){if(clearTimeout(n.deadline),n.deadline=void 0,n.kind===`relay`){t.avoidCarriers.clear();return}t.avoid.clear(),this.cacheWrite(()=>this.options.cache?.remember(e,n.candidate))}}cacheWrite(e){try{e()}catch(e){this.options.onError?.(e instanceof Error?e:Error(String(e)))}}send(e,t){if(this.closed)return;if(this.pendingPeers>0){this.waiting.length<256?this.waiting.push({topic:e,data:t}):this.viaRelay(e,t);return}let n=this.routes.get(e);if(n===void 0){this.viaRelay(e,t);return}let r=n.path;if(r.kind===`direct`&&r.socket.readyState===1){this.sendDirect(n,r,t);return}if(r.kind===`relay`&&this.now()<r.until){this.viaCarrier(n,r,t);return}if(r.kind===`resolving`){r.queue.length<256?r.queue.push(t):this.viaRelay(e,t);return}r.kind===`direct`&&this.reset(n);let i=[t];n.path={kind:`resolving`,queue:i},this.resolve(n,i)}sendDirect(e,t,n){Dn(n)&&this.armDeadline(e,t),t.socket.send(JSON.stringify({type:`message`,to:W(e.lanOut),data:n}))}viaRelay(e,t){let n=this.carriers().at(-1);if(n===void 0){queueMicrotask(()=>this.absent(e));return}n.send(e,t)}viaCarrier(e,t,n){Dn(n)&&t.carrier!==this.carriers().at(-1)&&this.armDeadline(e,t),t.carrier.send(e.route.outbound,n)}async resolve(e,t){let n=new Set;for(let r of this.options.sources){if(this.closed||e.path.kind!==`resolving`)return;for(let i of await this.look(r,e.route)){let r=On(i);if(n.size>=8)break;if(n.has(r)||e.avoid.has(r,this.now()))continue;n.add(r);let a=await this.probe(i,e.lanOut);if(a===void 0)continue;if(this.closed||e.path.kind!==`resolving`||this.routes.get(e.route.outbound)!==e){a.close();return}let o=this.useDirect(e,a,i);for(let n of t)this.sendDirect(e,o,n);return}}if(this.closed||e.path.kind!==`resolving`)return;this.fallBack(e);let r=e.path;for(let n of t)r.kind===`relay`?this.viaCarrier(e,r,n):this.viaRelay(e.route.outbound,n)}fallBack(e){let t=this.now(),n=this.carriers(),r=n.find(n=>!e.avoidCarriers.has(n,t))??n.at(-1);e.path=r===void 0?{kind:`unresolved`}:{kind:`relay`,until:t+this.recheckMs(),carrier:r}}recheckMs(){return this.options.relayRecheckMs??3e4}async look(e,t){let n=AbortSignal.timeout(e.timeoutMs??this.options.sourceTimeoutMs??1500),r=AbortSignal.any([n,this.abort.signal]);try{return await Promise.race([e.candidates(t,r),new Promise(e=>r.addEventListener(`abort`,()=>e([]),{once:!0}))])}catch{return[]}}probe(e,t){let n=W(t),r=kn();return new Promise(i=>{let a;try{a=(this.options.connect??(e=>new g(jn(e),{maxPayload:4096})))(e)}catch{i(void 0);return}let o=!1,s=e=>{o||(o=!0,clearTimeout(c),e||a.close(),i(e?a:void 0))},c=setTimeout(()=>s(!1),this.options.probeTimeoutMs??1500);c.unref?.(),a.on(`open`,()=>a.send(JSON.stringify({type:`probe`,to:n,nonce:r}))),a.on(`message`,e=>{let i=Mn(e);if(i?.to===n){if(i.type===`absent`){s(!1);return}s(hn(t,r,i.proof))}}),a.on(`error`,()=>s(!1)),a.on(`close`,()=>s(!1))})}armDeadline(e,t){t.deadline===void 0&&(t.deadline=setTimeout(()=>{e.path===t&&(t.kind===`direct`?e.avoid.fail(On(t.candidate),this.now(),this.recheckMs()):e.avoidCarriers.fail(t.carrier,this.now(),this.recheckMs()),this.reset(e),this.fallBack(e))},this.options.admissionTimeoutMs??2e4),t.deadline.unref?.())}useDirect(e,t,n){let r={kind:`direct`,socket:t,candidate:n};e.path=r;let i=()=>{e.path===r&&this.reset(e)};return t.on(`close`,i),t.on(`error`,i),t.on(`message`,t=>{let n=Mn(t);n?.type===`absent`&&n.to===W(e.lanOut)&&i()}),r}reset(e){let t=e.path;e.path={kind:`unresolved`},t.kind===`relay`&&clearTimeout(t.deadline),t.kind===`direct`&&(clearTimeout(t.deadline),t.socket.close())}onMessage(e){return this.messages.add(e),()=>this.messages.delete(e)}onAbsent(e){return this.absents.add(e),()=>this.absents.delete(e)}close(){if(!this.closed){this.closed=!0,this.abort.abort(),this.timer!==void 0&&clearTimeout(this.timer);for(let e of this.unsubscribes.splice(0))e();for(let e of this.routes.values())this.reset(e);this.routes.clear(),this.byDevice.clear(),this.messages.clear(),this.absents.clear(),this.waiting=[];for(let e of this.options.advertisers??[])e.close();this.options.listener.close().catch(()=>void 0)}}};async function Pn(e={}){let t=e.cache??ln(),n=t.lastListenPort(),r=await vn({...n===void 0?{}:{port:n},...e.host===void 0?{}:{host:e.host}});try{t.rememberListenPort(r.port)}catch(t){e.onError?.(t instanceof Error?t:Error(String(t)))}let i=e.mdns===!1?void 0:new wn({...e.onError===void 0?{}:{onError:e.onError},...e.mdns}),a=e.internet?.dht,o=e.internet?.signaling??[];return new Nn({...e.relay===void 0?{}:{relay:e.relay},...o.length>0?{signaling:o}:{},listener:r,sources:[on(t),...i===void 0?[]:[i],...a===void 0?[]:[a]],cache:t,advertisers:[...i===void 0?[]:[i],...a===void 0?[]:[a]],...e.onError===void 0?{}:{onError:e.onError}})}const Fn=Uint8Array.from([48,46,2,1,0,48,5,6,3,43,101,112,4,34,4,32]),q=new TextEncoder,In=new TextDecoder;function J(e){return e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength)}function Ln(e){let t=atob(e.replace(/-/g,`+`).replace(/_/g,`/`)),n=new Uint8Array(t.length);for(let e=0;e<t.length;e+=1)n[e]=t.charCodeAt(e);return n}function Y(e){let t=new Uint8Array(e.reduce((e,t)=>e+t.length,0)),n=0;for(let r of e)t.set(r,n),n+=r.length;return t}function Rn(e,t){if(e.length!==t.length)return!1;let n=0;for(let r=0;r<e.length;r+=1)n|=e[r]^t[r];return n===0}async function zn(e){if(e.length!==32)throw Error(`an Ed25519 seed is 32 bytes`);let t=await globalThis.crypto.subtle.importKey(`pkcs8`,J(Y([Fn,e])),{name:`Ed25519`},!0,[`sign`]),n=await globalThis.crypto.subtle.exportKey(`jwk`,t);if(typeof n.x!=`string`)throw Error(`Ed25519 public key unavailable`);return{publicKey:Ln(n.x),sign:async e=>new Uint8Array(await globalThis.crypto.subtle.sign({name:`Ed25519`},t,J(e)))}}async function Bn(e,t,n){if(e.length!==32||n.length!==64)return!1;try{let r=await globalThis.crypto.subtle.importKey(`raw`,J(e),{name:`Ed25519`},!1,[`verify`]);return await globalThis.crypto.subtle.verify({name:`Ed25519`},r,J(n),J(t))}catch{return!1}}function X(e,t,n){let r=[];return e!==void 0&&e.length>0&&r.push(q.encode(`4:salt${e.length}:`),e),r.push(q.encode(`3:seqi${t}e1:v${n.length}:`),n),Y(r)}async function Vn(e,t,n,r){if(r.length>999)throw Error(`record value exceeds 999 bytes`);if(t!==void 0&&t.length>64)throw Error(`salt exceeds 64 bytes`);if(!Number.isSafeInteger(n)||n<0)throw Error(`seq must be a non-negative integer`);let i=await e.sign(X(t,n,r));return{k:e.publicKey,...t===void 0?{}:{salt:t},seq:n,v:r,sig:i}}async function Z(e,t,n){return!Rn(e.k,t)||!Rn(e.salt??new Uint8Array,n??new Uint8Array)||e.v.length>999||!Number.isSafeInteger(e.seq)||e.seq<0?!1:Bn(t,X(n,e.seq,e.v),e.sig)}const Hn={hints:`bep44-salt`,revocation:`bep44-revocation-salt`};async function Un(e){return new Uint8Array(await globalThis.crypto.subtle.digest(`SHA-256`,J(Y(e))))}async function Wn(e,t,n,r,i=0){let[a,o]=await Promise.all([e.signingSeed(n,r,t),e.tag(Hn[t],n,r)]);if(i===0)return{key:await zn(a),salt:o};let s=q.encode(`chunk`),c=Uint8Array.of(i),[l,u]=await Promise.all([Un([s,a,c]),Un([s,o,c])]);return{key:await zn(l),salt:u}}async function Gn(e){let t=q.encode(JSON.stringify(e)),n=(await Un([t])).subarray(0,8),r=Math.max(1,Math.ceil(t.length/854));if(r>8)throw Error(`device lists too large to publish as records`);return Array.from({length:r},(e,i)=>{let a=new Uint8Array(864).fill(32);return a[0]=r,a[1]=i,a.set(n,2),a.set(t.subarray(i*854,(i+1)*854),10),a})}function Kn(e){let t=e[0];if(e.length===864&&e[1]===0)return t!==void 0&&t>=1&&t<=8?t:void 0}function qn(e){let t=e.length,n=e[0]?.subarray(2,10),r=[];for(let[i,a]of e.entries()){if(a.length!==864||a[0]!==t||a[1]!==i||!Jn(a.subarray(2,10),n))return;r.push(a.subarray(10))}return Xn(Y(r))}function Jn(e,t){return t!==void 0&&e.length===t.length&&e.every((e,n)=>e===t[n])}function Yn(e,t){let n=q.encode(JSON.stringify(e));if(n.length>t)throw Error(`record does not fit its fixed size`);let r=new Uint8Array(t).fill(32);return r.set(n),r}function Xn(e){try{return JSON.parse(In.decode(e))}catch{return}}function Zn(e,t){let n=[];for(let r of e){if(n.length>=t)break;r.host.length===0||r.host.length>64||n.push([r.host,r.port])}return n}function Qn(e,t=[]){let n=Zn(e,8),r=Zn(t,4);for(;;)try{return Yn({v:1,c:n,...r.length>0?{t:r}:{}},640)}catch(e){if(n.length>0)n.pop();else if(r.length>0)r.pop();else throw e}}const $n=/^[0-9A-Za-z.:%_-]{1,64}$/;function er(e){return nr(e,`c`,8)}function tr(e){return nr(e,`t`,4)}function nr(e,t,n){let r=Xn(e);if(typeof r!=`object`||!r)return[];let i=r,a=i[t];if(i.v!==1||!Array.isArray(a))return[];let o=[];for(let e of a.slice(0,n)){if(!Array.isArray(e)||e.length!==2)continue;let[t,n]=e;typeof t!=`string`||!$n.test(t)||typeof n!=`number`||!Number.isInteger(n)||n<1||n>65535||o.push({host:t,port:n})}return o}function rr(e,t=Math.random){let n=t();return Math.floor((Number.isFinite(n)?Math.min(Math.max(n,0),1):0)*Math.max(0,e))}const ir=9e4;function ar(e){if(typeof e!=`object`||!e)return-1;let t=e.seq;return typeof t==`number`&&Number.isSafeInteger(t)?t:-1}function or(e){return e instanceof Error?e:Error(String(e))}var sr=class{options;timeoutMs;scheduled=new Map;routes=[];listsFound;prefetchedEpoch;relaysFound=new Map;relayLookups=new Map;closed=!1;constructor(e){this.options=e,this.timeoutMs=e.lookupTimeoutMs??6e3}now(){return(this.options.now??Date.now)()}async candidates(e,t){let n=h(this.now()),r=await this.lookup(e,`hints`,n,t);t.aborted||this.rememberRelays(e,n,r);let i=[],a=new Set;for(let e of r.sort((e,t)=>t.epoch-e.epoch))for(let t of er(e.data)){let e=`${t.host}:${t.port}`;a.has(e)||(a.add(e),i.push(t))}return i}rememberRelays(e,t,n){let r=[...n].sort((e,t)=>t.epoch-e.epoch)[0],i=r===void 0?[]:tr(r.data);this.relaysFound.set(e.deviceId,{epoch:t,checkedAt:this.now(),endpoints:i})}async relayAdverts(e,t){let n=this.now(),r=h(n),i=e.slice(0,16),a=[];for(let e of i){let t=this.relaysFound.get(e.deviceId);t!==void 0&&t.epoch===r&&(t.endpoints.length>0||n-t.checkedAt<12e4)||a.push(this.lookUpRelay(e,r))}if(a.length>0){let e=new Promise(e=>{t.aborted&&e(),t.addEventListener(`abort`,()=>e(),{once:!0})});await Promise.race([Promise.all(a),e])}let o=new Set(e.map(e=>e.deviceId));for(let e of[...this.relaysFound.keys()])o.has(e)||this.relaysFound.delete(e);let s=new Map;for(let e of i){let t=this.relaysFound.get(e.deviceId)?.endpoints??[];t.length>0&&s.set(e.deviceId,t)}return s}lookUpRelay(e,t){let n=this.relayLookups.get(e.deviceId);if(n!==void 0)return n;let r=AbortSignal.timeout(this.timeoutMs),i=this.lookup(e,`hints`,t,r).then(n=>{!r.aborted&&!this.closed&&this.rememberRelays(e,t,n)}).finally(()=>this.relayLookups.delete(e.deviceId));return this.relayLookups.set(e.deviceId,i),i}async lookup(e,t,n,r){let i=[n-1,n,n+1].flatMap(n=>this.options.stores.map(async i=>{let a=await this.read(i,e,t,n,0,r);return a===void 0?void 0:{epoch:n,data:a}}));return(await Promise.all(i)).filter(e=>e!==void 0)}async read(e,t,n,r,i,a){try{let o=await Wn(t.rendezvous,n,`inbound`,r,i),s=await e.get(o.key.publicKey,o.salt,a);if(s===void 0)return;let c=await t.rendezvous.openRecord(s,r,n);return c?.epoch===r?c.hints:void 0}catch{return}}async lookupLists(e,t,n){let r=[t-1,t,t+1].flatMap(t=>this.options.stores.map(async r=>{let i=await this.read(r,e,`revocation`,t,0,n),a=i===void 0?void 0:Kn(i);if(i===void 0||a===void 0)return;let o=await Promise.all(Array.from({length:a-1},(i,a)=>this.read(r,e,`revocation`,t,a+1,n)));if(!o.some(e=>e===void 0))return qn([i,...o])}));return(await Promise.all(r)).filter(e=>e!==void 0)}advertise(e,t){if(this.closed)return Promise.resolve();this.routes=e;let n=h(this.now()),r=new Set(e.map(e=>e.outbound));for(let[e,t]of this.scheduled)r.has(e)||(clearTimeout(t.timer),this.scheduled.delete(e));this.prefetchedEpoch!==n&&(this.prefetchedEpoch=n,this.findLists(AbortSignal.timeout(3e4)));let i=this.options.maxPublishJitterMs??9e4;for(let r of e){let e=this.scheduled.get(r.outbound);if(e!==void 0&&e.epoch===n&&e.port===t)continue;e!==void 0&&clearTimeout(e.timer);let a=setTimeout(()=>{this.scheduled.delete(r.outbound),this.publish(r,t)},rr(i,this.options.random));a.unref?.(),this.scheduled.set(r.outbound,{timer:a,epoch:n,port:t})}return Promise.resolve()}async publish(e,t){if(this.closed)return;let n=this.now(),r=h(n),i=[];try{i.push({purpose:`hints`,chunk:0,plaintext:Qn(this.options.addresses().map(e=>({host:e,port:t})),this.options.relayEndpoints?.()??[])});let e=this.options.lists?.();if(e!==void 0){let t=await Gn({r:e.revocation,...e.signingKeyRevocation===void 0?{}:{s:e.signingKeyRevocation}});for(let[e,n]of t.entries())i.push({purpose:`revocation`,chunk:e,plaintext:n})}}catch(e){this.options.onError?.(or(e))}for(let{purpose:t,chunk:a,plaintext:o}of i)try{let i=await e.rendezvous.sealRecord(o,r,t),s=await Wn(e.rendezvous,t,`outbound`,r,a),c=await Promise.allSettled(this.options.stores.map(e=>e.put(s,i,n)));for(let e of c)e.status===`rejected`&&this.options.onError?.(or(e.reason))}catch(e){this.options.onError?.(or(e))}}async latestLists(e){let t=new Promise(t=>{e.aborted&&t(void 0),e.addEventListener(`abort`,()=>t(void 0),{once:!0})});return await Promise.race([this.findLists(e),t])??this.listsFound}async findLists(e){let t=h(this.now()),n=await Promise.all(this.routes.slice(0,16).map(n=>this.lookupLists(n,t,e))),r=[],i=[];for(let e of n){let t=[],n=[];for(let r of e){if(typeof r!=`object`||!r)continue;let e=r;e.r!==void 0&&t.push(e.r),e.s!==void 0&&n.push(e.s)}r.push(t),i.push(n)}let a=ur(r),o=ur(i),s=a.length===0&&o.length===0?void 0:{...a.length>0?{revocation:a}:{},...o.length>0?{signingKeyRevocation:o}:{}};return e.aborted||(this.listsFound=s),s}close(){if(!this.closed){this.closed=!0;for(let{timer:e}of this.scheduled.values())clearTimeout(e);this.scheduled.clear();for(let e of this.options.stores)e.close()}}};function cr(e){let t=new Set;return e.filter(e=>{let n=JSON.stringify(e);return t.has(n)?!1:(t.add(n),!0)})}function lr(e){return cr(e).sort((e,t)=>ar(t)-ar(e))}function ur(e){let t=e.map(e=>lr(e).slice(0,2)),n=[];for(let e=0;e<2;e+=1)n.push(...lr(t.flatMap(t=>t.slice(e,e+1))));return cr(n).slice(0,16)}function dr(e){let t=``;for(let n of e)t+=n.toString(16).padStart(2,`0`);return t}function fr(){let e=new Map,t=e=>e,n=(e,t)=>`${dr(e)}/${dr(t??new Uint8Array)}`;return{store:()=>({async put(t,r,i){let a=await Vn(t.key,t.salt,Math.floor(i/1e3),r);if(!await Z(a,a.k,a.salt))throw Error(`item refused`);let o=n(a.k,a.salt),s=e.get(o);if(s!==void 0&&s.seq>a.seq)throw Error(`item refused: older seq`);e.set(o,a)},async get(r,i){await Promise.resolve();let a=e.get(n(r,i)),o=a===void 0?void 0:t(a);if(o!==void 0)return await Z(o,r,i)?o.v:void 0},close:()=>void 0}),items:()=>[...e.values()],serve:e=>{t=e}}}const pr=`ybndrfg8ejkmcpqxot1uwisza345h769`;function mr(e){let t=``,n=0,r=0;for(let i of e)for(n=n<<8|i,r+=8;r>=5;)t+=pr[n>>>r-5&31],r-=5;return r>0&&(t+=pr[n<<5-r&31]),t}function hr(e){return Uint8Array.from([e>>>8&255,e&255])}function gr(e,t){let n=Y([...[`_r`,mr(e)].flatMap(e=>[Uint8Array.of(e.length),new TextEncoder().encode(e)]),Uint8Array.of(0)]),r=[];for(let e=0;e<t.length;e+=255){let n=t.subarray(e,e+255);r.push(Uint8Array.of(n.length),n)}t.length===0&&r.push(Uint8Array.of(0));let i=Y(r);return Y([Uint8Array.from([0,0,132,0,0,0,0,1,0,0,0,0]),n,hr(16),hr(1),Uint8Array.from([0,0,1,44]),hr(i.length),i])}function _r(e){let t=t=>(e[t]??0)<<8|(e[t+1]??0);if(e.length<12)return;let n=t(4),r=t(6),i=12,a=()=>{for(let t=0;t<128;t+=1){let t=e[i];if(t===void 0)return!1;if(t===0)return i+=1,!0;if((t&192)==192)return i+=2,!0;i+=1+t}return!1};for(let e=0;e<n;e+=1){if(!a())return;i+=4}for(let n=0;n<r;n+=1){if(!a()||i+10>e.length)return;let n=t(i),r=t(i+8),o=i+10,s=o+r;if(s>e.length)return;if(n===16){let t=[],n=o;for(;n<s;){let r=e[n];if(n+1+r>s)return;t.push(e.subarray(n+1,n+1+r)),n+=1+r}return Y(t)}i=s}}function vr(e){let t=new Uint8Array(8);return new DataView(t.buffer).setBigUint64(0,BigInt(e)),t}function yr(e){let t=e.length;for(;t>0&&e[t-1]===`/`;)--t;return e.slice(0,t)}function br(e){let t=e.fetch??globalThis.fetch.bind(globalThis),n=(e,t)=>`${yr(e)}/${mr(t)}`;return{async put(r,i,a,o){let s=gr(r.key.publicKey,i);if(s.length>999)throw Error(`record too large for a pkarr relay`);let c=Math.floor(a)*1e3,l=Y([await r.key.sign(X(void 0,c,s)),vr(c),s]);if(!(await Promise.allSettled(e.relays.map(async e=>{let i=await t(n(e,r.key.publicKey),{method:`PUT`,headers:{"content-type":`application/pkarr.org/relays#payload`},body:l.slice().buffer,...o===void 0?{}:{signal:o}});if(!i.ok)throw Error(`pkarr relay refused (${i.status})`)}))).some(e=>e.status===`fulfilled`))throw Error(`no pkarr relay took the record`)},async get(r,i,a){let o=await Promise.all(e.relays.map(async e=>{try{let i=await t(n(e,r),{signal:a});if(!i.ok)return;let o=new Uint8Array(await i.arrayBuffer());if(o.length<=72||o.length>1200)return;let s=o.subarray(0,64),c=Number(new DataView(o.buffer,o.byteOffset+64,8).getBigUint64(0)),l=o.slice(72);if(!Number.isSafeInteger(c)||!await Bn(r,X(void 0,c,l),s))return;let u=_r(l);return u===void 0?void 0:{seq:c,value:u}}catch{return}})),s;for(let e of o)e!==void 0&&(s===void 0||e.seq>s.seq)&&(s=e);return s?.value},close:()=>void 0}}const xr=Uint8Array.from([48,42,48,5,6,3,43,101,112,3,33,0]),Sr=(e,t,n)=>{if(n.length!==32||e.length!==64)return!1;try{return de(null,t,ce({key:Buffer.from(Y([xr,n])),format:`der`,type:`spki`}),e)}catch{return!1}};async function Cr(e){return new(await(import(`bittorrent-dht`))).default({verify:e})}function Q(e){return Buffer.from(e.buffer,e.byteOffset,e.byteLength)}function wr(e){if(e!==void 0)return new Promise((t,n)=>{e.aborted&&n(Error(`aborted`)),e.addEventListener(`abort`,()=>n(Error(`aborted`)),{once:!0})})}async function Tr(e={}){let t=await(e.createDht??Cr)(Sr),n=t=>e.onError?.(t);t.on(`error`,n),t.on(`warning`,n);let r=!1;return{async put(e,n,i,a){if(r)throw Error(`DHT store closed`);if(n.length>999)throw Error(`record value exceeds 999 bytes`);let o=await Vn(e.key,e.salt,Math.floor(i/1e3),n),s=new Promise((n,r)=>{t.put({k:Q(o.k),salt:Q(e.salt),seq:o.seq,v:Q(o.v),sig:Q(o.sig)},(e,t,i)=>{e===null?i===0?r(Error(`no DHT node took the record`)):n():r(e)})}),c=wr(a);await(c===void 0?s:Promise.race([s,c]))},async get(e,n,i){if(r||i.aborted)return;let a=_(`sha1`).update(Y([e,n])).digest(),o=new Promise(e=>{t.get(a,{salt:Q(n),cache:!1},(t,n)=>e(t===null?n:null))});try{let t=await Promise.race([o,wr(i)]);if(t?.v===void 0||t.k===void 0||t.sig===void 0)return;let r={k:new Uint8Array(t.k),salt:n,seq:t.seq??0,v:new Uint8Array(t.v),sig:new Uint8Array(t.sig)};return await Z(r,e,n)?r.v:void 0}catch{return}},close(){r||(r=!0,t.destroy())}}}const Er=/^[0-9a-f]{64}$/,Dr=/^[0-9a-f]{128}$/;function Or(e){return 2e4+((e[0]??0)<<8|(e[1]??0))%1e4}function kr(e){let t=``;for(let n of e)t+=String.fromCharCode(n);return btoa(t)}function Ar(e){try{let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e+=1)n[e]=t.charCodeAt(e);return n}catch{return}}function jr(e){if(typeof e!=`object`||!e)return;let t=e;if(!(typeof t.id!=`string`||!Er.test(t.id))&&!(typeof t.pubkey!=`string`||!Er.test(t.pubkey))&&!(typeof t.sig!=`string`||!Dr.test(t.sig))&&!(typeof t.kind!=`number`||!Number.isInteger(t.kind))&&!(typeof t.created_at!=`number`||!Number.isInteger(t.created_at))&&!(typeof t.content!=`string`||t.content.length>49152)&&!(!Array.isArray(t.tags)||t.tags.length!==0))return{id:t.id,pubkey:t.pubkey,sig:t.sig,kind:t.kind,created_at:t.created_at,content:t.content,tags:[]}}var Mr=class{options;messages=new Set;absents=new Set;outbound=new Map;inbound=new Map;subscription;chain=Promise.resolve();seen=new Set;routes=[];epoch;timer;closed=!1;constructor(e){this.options=e}now(){return(this.options.now??Date.now)()}report(e){this.options.onError?.(e instanceof Error?e:Error(String(e)))}enqueue(e){this.chain=this.chain.then(e).catch(e=>this.report(e))}whenIdle(){return this.chain}declarePresence(){}declarePeers(e){this.enqueue(()=>this.derive(e))}async derive(e){if(this.closed)return;this.routes=e;let t=h(this.now()),n=new Map,r=new Map;for(let i of e){let e=await i.rendezvous.signingSeed(`outbound`,t,`signal`),a=Or(await i.rendezvous.tag(`nostr-kind`,`outbound`,t));n.set(i.outbound,{route:i,epoch:t,secretKey:e,kind:a});for(let e of[t-1,t,t+1]){let t=await i.rendezvous.signingSeed(`inbound`,e,`signal`),n=Or(await i.rendezvous.tag(`nostr-kind`,`inbound`,e));r.set(ge(t),{route:i,epoch:e,kind:n})}}this.closed||(this.outbound=n,this.inbound=r,this.epoch=t,this.subscription?.close(),this.subscription=r.size===0?void 0:this.options.pool.subscribe({kinds:[...new Set([...r.values()].map(e=>e.kind))],authors:[...r.keys()],since:Math.floor(this.now()/1e3)-(this.options.maxEventAgeS??120)},e=>this.enqueue(()=>this.receive(e))),this.timer!==void 0&&clearTimeout(this.timer),this.timer=setTimeout(()=>this.declarePeers(this.routes),Math.max(0,(t+1)*a-this.now())),this.timer.unref?.())}send(e,t){this.closed||this.enqueue(async()=>{if(this.closed)return;this.epoch!==void 0&&h(this.now())!==this.epoch&&await this.derive(this.routes);let n=this.outbound.get(e);if(n===void 0){for(let t of this.absents)t(e);return}let r=new TextEncoder().encode(JSON.stringify(t)).length;if(r>32768)throw Error(`signal too large for a Nostr event`);let i=Yn(t,Math.ceil(r/512)*512),a=await n.route.rendezvous.sealRecord(i,n.epoch,`signal`),o=he({kind:n.kind,created_at:Math.floor(this.now()/1e3),tags:[],content:kr(a)},n.secretKey);if(!await this.options.pool.publish(o))throw Error(`no Nostr relay took the signal`)})}async receive(e){if(this.closed)return;let t=jr(e);if(t===void 0||this.seen.has(t.id))return;let n=this.inbound.get(t.pubkey);if(n===void 0||t.kind!==n.kind||Math.abs(Math.floor(this.now()/1e3)-t.created_at)>(this.options.maxEventAgeS??120)||!_e(t))return;this.remember(t.id);let r=Ar(t.content);if(r===void 0)return;let i=await n.route.rendezvous.openRecord(r,n.epoch,`signal`);if(i?.epoch!==n.epoch)return;let a=Xn(i.hints);if(!(a===void 0||this.closed))for(let e of this.messages)e(n.route.inbound,a)}remember(e){if(this.seen.add(e),this.seen.size<=2048)return;let t=this.seen.values().next().value;t!==void 0&&this.seen.delete(t)}onMessage(e){return this.messages.add(e),()=>this.messages.delete(e)}onAbsent(e){return this.absents.add(e),()=>this.absents.delete(e)}close(){this.closed||(this.closed=!0,this.timer!==void 0&&clearTimeout(this.timer),this.subscription?.close(),this.messages.clear(),this.absents.clear(),this.options.pool.close())}};function Nr(e,t){return e.kinds.includes(t.kind)&&e.authors.includes(t.pubkey)}function Pr(){let e=new Set,t=[],n=t=>{let n=JSON.parse(JSON.stringify(t));queueMicrotask(()=>{for(let t of[...e])Nr(t.filter,n)&&t.onEvent(n)})};return{pool:()=>{let r=new Set;return{publish:e=>{let r=jr(e);return r===void 0||!_e(r)?Promise.resolve(!1):(t.push(JSON.parse(JSON.stringify(e))),n(e),Promise.resolve(!0))},subscribe:(t,n)=>{let i={filter:t,onEvent:n};return e.add(i),r.add(i),{close:()=>{e.delete(i),r.delete(i)}}},close:()=>{for(let t of r)e.delete(t);r.clear()}}},events:t,inject:e=>n(e)}}function Fr(e){if(e.length===0)throw Error(`a Nostr relay pool needs at least one relay`);let t=new me,n=[...e];return{publish:async e=>(await Promise.allSettled(t.publish(n,e))).some(e=>e.status===`fulfilled`),subscribe:(e,r)=>t.subscribeMany(n,{kinds:[...e.kinds],authors:[...e.authors],...e.since===void 0?{}:{since:e.since}},{onevent:e=>r(e)}),close:()=>t.destroy()}}const Ir=[`wss://relay.damus.io`,`wss://nos.lol`,`wss://relay.primal.net`],Lr=[`https://pkarr.pubky.app`,`https://pkarr.pubky.org`,`https://dns.iroh.link/pkarr`],Rr=/^[A-Za-z0-9_-]{22}$/;var $=class extends Error{reason;constructor(e,t){super(`enrollment connection failed (${e})${t===void 0?``:`: ${t}`}`),this.name=`EnrollmentLinkError`,this.reason=e}};function zr(e,t){return typeof e==`string`&&e.length>0&&e.length<=t}function Br(e){if(typeof e!=`object`||!e||Array.isArray(e))return;let t=e;if(t.v!==1||typeof t.cid!=`string`||!Rr.test(t.cid))return;let n=t.cid;if(t.kind===`offer`||t.kind===`answer`)return zr(t.sdp,49152)?{kind:t.kind,cid:n,sdp:t.sdp}:void 0;if(t.kind===`ice`){let e=t.candidate;if(typeof e!=`object`||!e||Array.isArray(e))return;let r=e;return!zr(r.candidate,2048)||!zr(r.mid,64)?void 0:{kind:`ice`,cid:n,candidate:{candidate:r.candidate,mid:r.mid}}}}function Vr(){let e=new Uint8Array(16);return globalThis.crypto.getRandomValues(e),Buffer.from(e).toString(`base64url`)}var Hr=class{role;cid;options;onBound;onFailed;peer;channel;localFingerprint;remoteFingerprint;tookRemoteDescription=!1;sentDescription=!1;localCandidates=[];remoteCandidates=0;chain=Promise.resolve();stopAwaiting;timer;done=!1;early=[];frameHandlers=new Set;closeHandlers=new Set;constructor(e,t,n,r,i){this.role=e,this.cid=t,this.options=n,this.onBound=r,this.onFailed=i,this.timer=setTimeout(()=>this.fail(new $(`timeout`)),n.connectTimeoutMs??2e4)}async offer(){try{let e=this.createPeer();this.adopt(e.createDataChannel(`agent-enroll`));let t=await e.createOffer();if(this.done)return;this.localFingerprint=p(t),this.sendDescription({kind:`offer`,cid:this.cid,sdp:t})}catch(e){this.fail(new $(`signaling`,Ur(e)))}}onSignal(e){this.done||(this.chain=this.chain.then(()=>this.apply(e)).catch(e=>this.fail(new $(`signaling`,Ur(e)))))}async apply(e){if(this.done)return;if(e.kind===`ice`){if(this.peer===void 0||++this.remoteCandidates>64)return;this.peer.addRemoteCandidate(e.candidate);return}let t=this.role===`offerer`?`answer`:`offer`;if(e.kind!==t||this.tookRemoteDescription)return;this.tookRemoteDescription=!0;let n;try{n=m(e.sdp).algorithm}catch(e){this.fail(new $(`channel-binding`,Ur(e)));return}if(this.role===`offerer`){let t=this.peer;if(t===void 0)return;t.acceptAnswer(e.sdp),this.awaitCertificate(t,n);return}let r=this.createPeer(),i=await r.acceptOffer(e.sdp);this.done||(this.localFingerprint=p(i),this.sendDescription({kind:`answer`,cid:this.cid,sdp:i}),this.awaitCertificate(r,n))}createPeer(){let e=new T({...this.options.iceServers===void 0?{}:{iceServers:this.options.iceServers},...this.options.loadDataChannel===void 0?{}:{loadDataChannel:this.options.loadDataChannel}});return this.peer=e,e.onLocalCandidate(e=>{if(this.done)return;let t={kind:`ice`,cid:this.cid,candidate:{candidate:e.candidate,mid:e.mid}};this.sentDescription?this.send(t):this.localCandidates.length<64&&this.localCandidates.push(t)}),e.onStateChange(e=>{(e===`failed`||e===`closed`)&&this.fail(new $(`closed`,`connection ${e}`))}),e.onDataChannel(e=>{this.role===`answerer`&&this.channel===void 0&&!this.done?this.adopt(e):e.close()}),e}send(e){this.options.relay.send(this.options.outbound,{v:1,...e})}sendDescription(e){this.send(e),this.sentDescription=!0;for(let e of this.localCandidates.splice(0))this.send(e)}awaitCertificate(e,t){this.stopAwaiting=S(e,t,e=>{this.remoteFingerprint=e,this.maybeBound()},e=>this.fail(new $(`channel-binding`,e)))}adopt(e){this.channel=e,e.onMessage(e=>this.inbound(e)),e.onStateChange(e=>{e===`open`?this.maybeBound():e===`closed`&&this.closed()}),e.readyState===`open`&&this.maybeBound()}inbound(e){if(e.length>262144){this.closeAll();return}if(this.frameHandlers.size===0){if(this.early.length>=16){this.closeAll();return}this.early.push(e);return}this.deliver(e)}deliver(e){let t;try{t=JSON.parse(e)}catch{t=void 0}for(let e of this.frameHandlers)e(t)}maybeBound(){let e=this.channel;if(this.done||e===void 0||e.readyState!==`open`)return;let t=this.localFingerprint,n=this.remoteFingerprint;t!==void 0&&n!==void 0&&(this.done=!0,clearTimeout(this.timer),this.stopAwaiting?.(),this.onBound({localFingerprint:t,remoteFingerprint:n,send:t=>{try{e.send(JSON.stringify(t))}catch{}},onFrame:e=>{this.frameHandlers.add(e);let t=this.early.splice(0);return t.length>0&&queueMicrotask(()=>t.forEach(e=>this.deliver(e))),()=>this.frameHandlers.delete(e)},onClose:t=>e.readyState===`closed`?(queueMicrotask(t),()=>void 0):(this.closeHandlers.add(t),()=>this.closeHandlers.delete(t)),close:()=>this.closeAll()}))}closed(){if(!this.done){this.fail(new $(`closed`,`data channel closed`));return}this.closeAll()}closeAll(){this.channel?.close();let e=this.peer;e!==void 0&&setTimeout(()=>e.close(),250).unref?.();let t=[...this.closeHandlers];this.closeHandlers.clear(),this.frameHandlers.clear();for(let e of t)e()}fail(e){this.done||(this.done=!0,clearTimeout(this.timer),this.stopAwaiting?.(),this.channel?.close(),this.peer?.close(),this.onFailed(e))}};function Ur(e){return e instanceof Error?e.message:String(e)}function Wr(e){return new Promise((t,n)=>{let r=[],i=()=>{for(let e of r.splice(0))e()},a=new Hr(`offerer`,Vr(),e,e=>{i(),t(e)},e=>{i(),n(e)});r.push(e.relay.onMessage((t,n)=>{if(t!==e.inbound)return;let r=Br(n);r!==void 0&&r.cid===a.cid&&a.onSignal(r)}),e.relay.onAbsent(t=>{t===e.outbound&&a.fail(new $(`absent`))})),e.relay.declarePresence([e.inbound]),a.offer()})}function Gr(e){let t,n=!1,r=e.relay.onMessage((r,i)=>{if(n||r!==e.inbound)return;let a=Br(i);if(a===void 0)return;if(t!==void 0){a.cid===t.cid&&t.onSignal(a);return}if(a.kind!==`offer`)return;let o=new Hr(`answerer`,a.cid,e,r=>{if(n){r.close();return}r.onClose(()=>{t===o&&(t=void 0)}),e.onChannel(r)},n=>{t===o&&(t=void 0),e.onAttemptFailed?.(n)});t=o,o.onSignal(a)});return e.relay.declarePresence([e.inbound]),{close:()=>{n||(n=!0,r(),t?.fail(new $(`closed`,`no longer listening`)))}}}export{ir as DEFAULT_MAX_PUBLISH_JITTER_MS,Ir as DEFAULT_NOSTR_RELAYS,Lr as DEFAULT_PKARR_RELAYS,Ft as DEFAULT_RELAY_CREDENTIAL_TTL_MS,xt as DEFAULT_TURN_QUOTAS,St as DEFAULT_UNAUTHENTICATED_LIMITS,tn as DeviceMeshNode,Nn as DiscoveringMeshRelay,$ as EnrollmentLinkError,an as MAX_CACHED_CANDIDATES,$e as MAX_MESH_MESSAGE_CHARS,It as MAX_RELAY_CREDENTIAL_TTL_MS,G as MESH_MDNS_SERVICE,sr as MeshDht,nt as MeshLinkEndedError,wn as MeshMdns,B as MeshRelayNeededError,Ht as MeshTurnRelay,Mr as NostrMeshRelay,w as RtcChannel,T as RtcPeer,Pt as TurnServer,Ke as WebRtcTransport,rn as WsMeshRelayClient,Ze as WsSignalingClient,on as addressCacheSource,fr as createInMemoryItemNetwork,Tn as createInMemoryMdnsBus,ln as createInMemoryMeshAddressCache,nn as createInMemoryMeshRelayHub,Pr as createInMemoryNostrHub,Je as createInMemorySignalingPair,Fr as createNostrRelayPool,br as createPkarrRelayStore,Wr as dialEnrollment,ke as handoffGrantFrame,Oe as judgeHandoffGrant,Gr as listenForEnrollment,xe as loadDataChannel,bn as localInterfaceAddresses,Ne as localProofFrame,zt as meshRelayCredential,Vt as meshRelayIceServers,Cn as paddedInstanceCount,Pn as startLanMeshRelay,Tr as startMainlineDhtStore,vn as startMeshLanListener};
1
+ import{createRequire as e}from"node:module";import{HISTORY_PAGE_MAX_BYTES as t,createOutboundDelivery as n,createSessionMessageHandler as r}from"@robota-sdk/agent-transport";import{resolveAdmission as i}from"@robota-sdk/agent-transport/node";import{RENDEZVOUS_EPOCH_MS as a,decodeDeviceRevocationList as o,decodeDeviceRoster as s,decodeEnrollFrame as c,decodePairingFrame as l,decodeReconnectFrame as u,decodeSigningKeyRevocation as d,deriveIdentityId as f,derivePairRendezvous as ee,extractDtlsFingerprint as p,extractDtlsFingerprintAttribute as m,importPublicKey as te,rendezvousEpoch as h,startDeviceHandshake as ne,startHostReconnect as re,startPairingHandshake as ie,verifyDeviceChain as ae}from"@robota-sdk/agent-remote-pairing";import g,{WebSocketServer as oe}from"ws";import{ConnectionAuthority as se}from"@robota-sdk/agent-interface-session-mobility";import{createHash as _,createHmac as v,createPublicKey as ce,randomBytes as le,randomInt as ue,timingSafeEqual as y,verify as de}from"node:crypto";import{createSocket as fe}from"node:dgram";import{isIPv4 as b,isIPv6 as pe}from"node:net";import{networkInterfaces as x}from"node:os";import{SimplePool as me}from"nostr-tools/pool";import{finalizeEvent as he,getPublicKey as ge,verifyEvent as _e}from"nostr-tools/pure";function ve(e,t){return n(t=>e.send(JSON.stringify(t)),(e,n)=>t(e,n),()=>e.bufferedAmount)}const ye=/^[0-9A-F]{2}(?::[0-9A-F]{2})+$/;function S(e,t,n,r){let i=!1,a=()=>{if(i)return;i=!0;let a=e.remoteFingerprint();if(a===void 0){r(`the DTLS layer exposed no remote certificate`);return}let o=a.value.toUpperCase();if(a.algorithm.toLowerCase()!==t.toLowerCase()){r(`the remote certificate was checked with ${a.algorithm}, not ${t}`);return}if(!ye.test(o)){r(`the remote certificate fingerprint is malformed`);return}n(o)},o=e=>{i||(i=!0,r(`the connection ended ${e} before DTLS completed`))};if(e.state===`connected`)return a(),()=>void 0;if(e.state===`failed`||e.state===`closed`)return o(e.state),()=>void 0;let s=e.onStateChange(e=>{if(e===`connected`)a();else if(e===`failed`||e===`closed`)o(e);else return;s()});return s}const be=t=>e(import.meta.url)(t);function xe(e=be){try{let t=e(`node-datachannel`);if(typeof t?.PeerConnection!=`function`)throw Error(`no PeerConnection export`);return t}catch{throw Error(`WebRTC transport unavailable — the optional dependency "node-datachannel" is not installed or has no prebuilt binary for this platform (${process.platform}-${process.arch}).`)}}function C(e){try{return e?.()}catch{return}}function Se(e){return e instanceof Error?e.message:String(e)}const Ce={stun:3478,turn:3478,turns:5349};function we(e){let t=/^(stuns?|turns?):([^:?]+|\[[^\]]+\])(?::(\d{1,5}))?(?:\?transport=(udp|tcp))?$/i.exec(e.urls);if(!t)throw Error(`unsupported ICE server url: ${e.urls}`);let n=t[1].toLowerCase(),r=t[2].replace(/^\[|\]$/g,``),i=t[3]===void 0?Ce[n]??3478:Number(t[3]);return n===`stun`||n===`stuns`?`stun:${r}:${i}`:{hostname:r,port:i,...e.username===void 0?{}:{username:e.username},...e.credential===void 0?{}:{password:e.credential},relayType:n===`turns`?`TurnTls`:t[4]?.toLowerCase()===`tcp`?`TurnTcp`:`TurnUdp`}}function Te(e){return typeof e==`string`?e:Buffer.from(e).toString(`utf8`)}var w=class{native;fault;stateValue;closeCauseValue;closedLocally=!1;messageHandlers=new Set;stateHandlers=new Set;constructor(e,t){this.native=e,this.fault=t,this.stateValue=e.isOpen()?`open`:`connecting`,e.onOpen(()=>this.guard(()=>this.setState(`open`))),e.onClosed(()=>this.guard(()=>this.closedWith(`closed by the peer or the transport`))),e.onError(e=>this.guard(()=>this.closedWith(`error: ${e}`))),e.onMessage(e=>this.guard(()=>{if(this.closedLocally)return;let t=Te(e);for(let e of this.messageHandlers)e(t)}))}guard(e){try{e()}catch(e){this.closeCauseValue??=`handler error: ${Se(e)}`,this.fault(e)}}closedWith(e){this.closeCauseValue??=e,this.setState(`closed`)}get closeCause(){return this.closeCauseValue}setState(e){if(this.stateValue!==e&&this.stateValue!==`closed`){this.stateValue=e;for(let t of this.stateHandlers)t(e)}}get readyState(){return this.stateValue}get label(){try{return this.native.getLabel?.()??``}catch{return``}}get bufferedAmount(){try{return this.native.bufferedAmount()}catch{return 0}}send(e){if(this.stateValue!==`open`)throw Error(`data channel is not open`);this.native.sendMessage(e)}onMessage(e){return this.messageHandlers.add(e),()=>this.messageHandlers.delete(e)}onStateChange(e){return this.stateHandlers.add(e),()=>this.stateHandlers.delete(e)}close(){if(this.stateValue===`closed`)return;this.closedLocally=!0;let e=this.native;setTimeout(()=>{try{e.close()}catch{}},250).unref?.(),this.closedWith(`closed by this side`)}},T=class{native;stateValue=`new`;stateHandlers=new Set;candidateHandlers=new Set;channelHandlers=new Set;descriptionWaiters=[];hasRemoteDescription=!1;history=[];closedBy;handlerError;localCandidateCount=0;remoteCandidateCount=0;heldLocalCandidates=[];earlyCandidates=[];closed=!1;constructor(e={}){let t=(e.loadDataChannel??xe)();this.native=new t.PeerConnection(`agent`,{iceServers:(e.iceServers??[]).map(we),...e.forceTurn===!0?{iceTransportPolicy:`relay`}:{},disableAutoNegotiation:!0}),this.native.onStateChange(e=>this.guard(()=>{if(e!==this.stateValue&&this.stateValue!==`closed`){this.stateValue=e,this.remember(this.stateValue);for(let e of this.stateHandlers)e(this.stateValue)}})),this.native.onLocalCandidate((e,t)=>this.guard(()=>{let n=e.startsWith(`a=`)?e.slice(2):e;if(n.length!==0){if(!this.hasRemoteDescription){this.heldLocalCandidates.push({candidate:n,mid:t});return}this.handOut({candidate:n,mid:t})}})),this.native.onLocalDescription(e=>this.guard(()=>{for(let t of this.descriptionWaiters.splice(0))t(e)})),this.native.onDataChannel(e=>this.guard(()=>{let t=new w(e,e=>this.fault(e));for(let e of this.channelHandlers)e(t)}))}guard(e){try{e()}catch(e){this.fault(e)}}fault(e){this.closed||(this.closedBy=`handler-error`,this.handlerError=Se(e),this.close())}remember(e){this.history.length<16&&this.history.push(e)}diagnostics(){let e=C(this.native.iceState?.bind(this.native)),t=C(this.native.gatheringState?.bind(this.native)),n=C(this.native.signalingState?.bind(this.native));return{state:this.stateValue,...e===void 0?{}:{ice:e},...t===void 0?{}:{gathering:t},...n===void 0?{}:{signaling:n},history:[...this.history],...this.closedBy===void 0?{}:{closedBy:this.closedBy},...this.handlerError===void 0?{}:{handlerError:this.handlerError},localCandidates:this.localCandidateCount,remoteCandidates:this.remoteCandidateCount}}get state(){return this.stateValue}createDataChannel(e){return new w(this.native.createDataChannel(e),e=>this.fault(e))}localDescription(e){return new Promise((t,n)=>{this.descriptionWaiters.push(t);try{this.native.setLocalDescription(e)}catch(e){let r=this.descriptionWaiters.indexOf(t);r>=0&&this.descriptionWaiters.splice(r,1),n(e instanceof Error?e:Error(String(e)))}})}createOffer(){return this.localDescription(`offer`)}async acceptOffer(e){return this.native.setRemoteDescription(e,`offer`),this.remoteDescriptionApplied(),this.localDescription(`answer`)}acceptAnswer(e){this.native.setRemoteDescription(e,`answer`),this.remoteDescriptionApplied()}remoteDescriptionApplied(){this.hasRemoteDescription=!0;for(let e of this.earlyCandidates.splice(0))this.addRemoteCandidate(e);let e=this.heldLocalCandidates.splice(0);this.guard(()=>{for(let t of e)this.handOut(t)})}handOut(e){if(!this.closed){this.localCandidateCount+=1;for(let t of this.candidateHandlers)t(e)}}addRemoteCandidate(e){if(!this.closed){if(!this.hasRemoteDescription){this.earlyCandidates.length<64&&this.earlyCandidates.push(e);return}try{this.native.addRemoteCandidate(e.candidate,e.mid),this.remoteCandidateCount+=1}catch{}}}remoteFingerprint(){if(this.stateValue===`connected`)try{let e=this.native.remoteFingerprint();return e.value.length>0?e:void 0}catch{return}}onStateChange(e){return this.stateHandlers.add(e),()=>this.stateHandlers.delete(e)}onLocalCandidate(e){return this.candidateHandlers.add(e),()=>this.candidateHandlers.delete(e)}onDataChannel(e){return this.channelHandlers.add(e),()=>this.channelHandlers.delete(e)}close(){if(!this.closed){this.closed=!0,this.closedBy??=`local`;try{this.native.close()}catch{}if(this.stateValue!==`closed`){this.stateValue=`closed`,this.remember(`closed`);for(let e of this.stateHandlers)e(`closed`)}}}};function Ee(e,t){let n=t===`operator-approval`;return e.localPeer!==void 0&&t!==`local-proof`&&t!==`handoff-grant`&&!n?`local-proof`:e.handoffGrant!==void 0&&t!==`handoff-grant`&&!n?`handoff-grant`:e.connectionApproval!==void 0&&!n?`operator-approval`:null}function De(e){return typeof e==`object`&&!!e&&e.t===`handoff-grant`&&e.grant!==void 0}function E(e){return{admitted:!1,trust:`unproven`,reason:e}}async function Oe(e,t){if(t===void 0)return E(`no hand-off grant verifier is configured for this channel`);if(!De(e))return E(`expected a handoff-grant frame carrying the signed grant`);try{let n=await t.verify(e.grant);return n.admitted&&n.trust===`same-user-same-host`?E(`the grant verifier returned same-user-same-host. A cross-device grant proves the user, not the machine — see SEC-010 for what same-host requires.`):!n.admitted||t.consent===void 0||await t.consent(n)?n:E(`the person at this machine declined the transfer`)}catch(e){return E(`the grant verifier could not decide: ${e instanceof Error?e.message:`unknown error`}`)}}function ke(e){return{t:`handoff-grant`,grant:e}}function Ae(e){return typeof e==`object`&&!!e&&e.t===`local-proof`&&typeof e.nonce==`string`}function je(e){return{admitted:!1,trust:`unproven`,reason:e}}function Me(e,t){if(t===void 0)return je(`no local-peer proof is configured for this channel`);if(!Ae(e))return je(`expected a local-proof frame carrying the rendezvous nonce`);try{return t.redeem(e.nonce)}catch(e){return je(`the rendezvous ledger could not decide: ${e instanceof Error?e.message:`unknown error`}`)}}function Ne(e){return{t:`local-proof`,nonce:e}}function Pe(e,t){try{e.send(t)}catch{}}function Fe(e){try{e.close()}catch{}}function Ie(e,t,n){try{e?.(t,n)}catch{}}const D=Object.freeze({send:Pe,close:Fe,reportDeliveryError:Ie});function Le(e,t,n,r,i,a=ie){let o=a(e.cryptoContext,{secret:t,role:n,localFingerprint:e.localFingerprint,remoteFingerprint:e.remoteFingerprint,send:t=>D.send(e.channel,JSON.stringify(t)),...e.timeoutMs===void 0?{}:{timeoutMs:e.timeoutMs}});return o.result.then(r,i),o}function Re(e,t,n,r){let i=re(e.cryptoContext,{hostIdentityId:t.hostIdentityId,localFingerprint:e.localFingerprint,remoteFingerprint:e.remoteFingerprint,hostPrivateKey:t.hostPrivateKey,resolveDevicePublicKey:t.resolveDevicePublicKey,send:t=>D.send(e.channel,JSON.stringify(t)),...e.timeoutMs===void 0?{}:{timeoutMs:e.timeoutMs}});return i.result.then(n,r),i}function ze(e){return l(e).ok}function Be(e){return u(e).ok}function Ve(e){return c(e).ok}function He(e,n,i){let a=e.resumeBridge;if(a)return a.attach(t=>e.channel.send(t),{awaitResume:n,onDeliveryError:i,pendingBytes:()=>e.channel.bufferedAmount}),{onSessionMessage:e=>a.onClientMessage(e),cleanup:()=>a.detach()};let{onMessage:o,cleanup:s}=(e.createHandler??r)({session:e.session,deliver:ve(e.channel,i),maxFrameBytes:t,...e.personalUsageReporter?{personalUsageReporter:e.personalUsageReporter}:{},...e.usageReporter?{usageReporter:e.usageReporter}:{},...e.storedSessionUsageReporter?{storedSessionUsageReporter:e.storedSessionUsageReporter}:{},...e.surface?{surface:e.surface}:{},...e.commandSurfaceLocality?{commandSurfaceLocality:e.commandSurfaceLocality}:{}});return{onSessionMessage:o,cleanup:s}}var Ue=class{options;state;onSessionMessage;handlerCleanup;pairingController;reconnectController;pendingResult;pendingViaReconnect=!1;pendingDeviceId;pendingEnrollment;heldFrames=[];heldChars=0;approvalAbort;constructor(e){this.options=e,e.reconnect?this.state=`awaiting-mode`:(this.state=`pairing`,this.startFirstPair())}onInbound(e){if(this.state===`closed`)return;if(this.state===`accepted`){this.onSessionMessage?.(e);return}if(this.state===`operator-approval`){this.hold(e);return}let t;try{t=JSON.parse(e)}catch{return}if(this.state===`awaiting-mode`){Be(t)&&t.t===`rc-hello`?(this.state=`reconnecting`,this.startReconnect(),this.reconnectController?.onFrame(t)):ze(t)&&t.t===`pair-nonce`&&(this.state=`pairing`,this.startFirstPair(),this.pairingController?.onFrame(t));return}if(this.state===`pairing`){ze(t)?this.pairingController?.onFrame(t):this.hold(e);return}if(this.state===`reconnecting`){Be(t)?this.reconnectController?.onFrame(t):this.hold(e);return}if(this.state===`local-proof`){let e=Me(t,this.options.localPeer);this.options.localPeer?.onAdmission?.(e),e.admitted?this.accept(this.pendingResult,this.pendingViaReconnect):this.rejectAndClose();return}if(this.state===`handoff-grant`){this.judgeGrantFrame(t);return}if(this.state===`enrolling`){Ve(t)?this.completeEnrollment(t.spki):this.hold(e);return}}cleanup(){this.state=`closed`,this.withdrawApproval(),this.handlerCleanup?.(),this.handlerCleanup=void 0,this.onSessionMessage=void 0}onChannelClosed(){this.state!==`accepted`&&this.state!==`closed`&&this.rejectAndClose()}withdrawApproval(){this.heldFrames=[],this.heldChars=0,this.approvalAbort?.abort(),this.approvalAbort=void 0}startFirstPair(){this.pairingController=Le(this.options,this.options.secret,this.options.role,e=>this.onFirstPairAccepted(e),()=>this.rejectAndClose(),this.options.startHandshake??ie)}startReconnect(){let e=this.options.reconnect;if(!e){this.rejectAndClose();return}this.reconnectController=Re(this.options,e,e=>{this.pendingDeviceId=e.deviceId,this.accept(void 0,!0)},()=>this.rejectAndClose())}onFirstPairAccepted(e){if(this.state!==`pairing`)return;this.pendingResult=e;let t=this.options.reconnect;if(!t){this.accept(e);return}this.state=`enrolling`,D.send(this.options.channel,JSON.stringify({t:`enroll-key`,spki:t.hostPublicSpki})),this.replayHeld()}completeEnrollment(e){if(this.state===`enrolling`){if(!this.options.reconnect){this.rejectAndClose();return}(async()=>{try{await te(e);let t=await f(e);if(this.state!==`enrolling`)return;this.pendingDeviceId=t,this.pendingEnrollment={deviceId:t,spki:e},this.accept(this.pendingResult)}catch{this.rejectAndClose()}})()}}accept(e,t=!1){if(this.state===`closed`||this.state===`accepted`)return;let n=Ee(this.options,this.state);if(n!==null){this.pendingResult=e??this.pendingResult,this.pendingViaReconnect=t,this.state=n,n===`operator-approval`&&this.askOperator(),this.replayHeld();return}let r=this.pendingEnrollment;if(this.pendingEnrollment=void 0,r!==void 0)try{this.options.reconnect?.onEnroll(r.deviceId,r.spki)}catch{this.rejectAndClose();return}let i=He(this.options,t,(e,t)=>this.handleSessionDeliveryError(e,t));this.onSessionMessage=i.onSessionMessage,this.handlerCleanup=i.cleanup,this.state=`accepted`,this.options.onAccept?.(e);let a=this.heldFrames;this.heldFrames=[],this.heldChars=0;for(let e of a){if(this.state!==`accepted`)return;this.onSessionMessage?.(e)}}replayHeld(){let e=this.heldFrames;this.heldFrames=[],this.heldChars=0;for(let t of e){if(this.state===`closed`)return;this.onInbound(t)}}hold(e){this.heldChars+=e.length,this.heldFrames.push(e),(this.heldFrames.length>32||this.heldChars>262144)&&this.rejectAndClose()}async askOperator(){let e=new AbortController;this.approvalAbort=e;let t={...this.pendingDeviceId===void 0?{}:{deviceId:this.pendingDeviceId},viaReconnect:this.pendingViaReconnect,signal:e.signal},n=!1;try{n=await this.options.connectionApproval?.approve(t)===!0}catch{n=!1}this.state!==`operator-approval`||e.signal.aborted||(this.approvalAbort=void 0,n?this.accept(this.pendingResult,this.pendingViaReconnect):this.rejectAndClose())}async judgeGrantFrame(e){let t=await Oe(e,this.options.handoffGrant);this.state===`handoff-grant`&&(this.options.handoffGrant?.onAdmission?.(t),t.admitted?this.accept(this.pendingResult,this.pendingViaReconnect):this.rejectAndClose())}rejectAndClose(){this.state!==`closed`&&(this.state=`closed`,this.withdrawApproval(),D.close(this.options.channel),this.options.onReject?.())}handleSessionDeliveryError(e,t){this.state!==`closed`&&(this.state=`closed`,this.handlerCleanup?.(),this.handlerCleanup=void 0,this.onSessionMessage=void 0,D.reportDeliveryError(this.options.onDeliveryError,e,t),D.close(this.options.channel))}};function We(e){return Object.assign(Error(`WebRtcTransport ${e}.`),{name:`TransportLifecycleError`,code:e,transportName:`webrtc`})}var Ge=class{options;generation=0;paired=!1;dropped=!1;constructor(e){this.options=e}reset(e){this.generation=e,this.paired=!1,this.dropped=!1}accept(e){e===this.generation&&(this.paired=!0)}handleDrop(e){e!==this.generation||!this.paired||this.dropped||(this.dropped=!0,this.options.cleanup(),this.options.onDropped())}handleFailure(e,t,n,r){if(t!==this.generation||this.dropped)return;let i=this.paired;i&&(this.dropped=!0);try{this.options.onDeliveryError(n,r)}catch{}this.options.cleanup();try{e.close()}catch{}i&&this.options.onDropped()}},Ke=class{options;name=`webrtc`;lifecycle=Object.freeze({kind:`service`});defaultEnabled=!1;optionsSchema={};session;peer;unsubscribeSignal;cleanupHandler;generation=0;localFingerprint;pairingGate;offerSent=!1;localCandidates=[];answered=!1;pendingFrames=[];stopAwaitingCertificate;deliveryLifecycle;constructor(e){if(this.options=e,this.deliveryLifecycle=new Ge({cleanup:()=>{this.cleanupHandler?.(),this.pairingGate?.cleanup()},onDropped:()=>this.options.onDropped?.(),onDeliveryError:(e,t)=>this.options.onDeliveryError?.(e,t)}),this.options.secret&&this.options.open===!0)throw Error("WebRtcTransport: `secret` and `open: true` are contradictory. A pairing secret gates the data channel; `open` runs without a gate. Pass one.");if(this.options.secret===void 0||this.options.secret===``){if(this.options.open!==!0)throw Error('WebRtcTransport: no pairing `secret` and no explicit `open`. Pass a `secret` to gate the data channel, or `{ open: true, openReason: "…" }` to run without pairing on purpose.');i({open:!0,...this.options.openReason===void 0?{}:{openReason:this.options.openReason}})}}validateOptions(){return!0}attach(e){this.session=e}createPeer(){return new T({...this.options.iceServers?{iceServers:this.options.iceServers}:{},...this.options.forceTurn?{forceTurn:!0}:{},...this.options.loadDataChannel?{loadDataChannel:this.options.loadDataChannel}:{}})}wireSignaling(e,t,n,r){let i=this.options.signaling;e.onLocalCandidate(t=>{r===this.generation&&e===this.peer&&(this.offerSent?this.sendCandidate(t):this.localCandidates.length<64&&this.localCandidates.push(t))});let a=Promise.resolve();this.unsubscribeSignal=i.onSignal(i=>{r===this.generation&&(a=a.then(async()=>{if(r===this.generation&&e===this.peer){if(i.kind===`answer`){if(this.answered)return;this.answered=!0;let a=this.remoteFingerprintAlgorithm(t,i.data);if(this.options.secret&&a===void 0)return;let o=i.data?.sdp;if(typeof o!=`string`)return;e.acceptAnswer(o),a!==void 0&&this.awaitVerifiedCertificate(e,t,n,a,r)}else if(i.kind===`ice`){let t=qe(i.data);t!==void 0&&e.addRemoteCandidate(t)}}}).catch(()=>{r===this.generation&&this.failPairing(t)}))})}sendCandidate(e){this.options.signaling.send({kind:`ice`,data:{candidate:e.candidate,sdpMid:e.mid,sdpMLineIndex:0}})}requireCurrentPeer(e,t){if(t!==this.generation||this.peer!==e)throw e.close(),Error(`WebRtcTransport startup was stopped.`)}async start(){let e=this.session;if(!e)throw We(`not-attached`);if(this.peer)throw We(`already-started`);let t=++this.generation;this.deliveryLifecycle.reset(t),this.answered=!1,this.offerSent=!1,this.localCandidates=[],this.pendingFrames=[];let n=this.createPeer();this.peer=n;let r=this.options.signaling,i=n.createDataChannel(`agent-session`);this.wireChannel(i,e,t),this.wireSignaling(n,i,e,t);let a=await n.createOffer();this.requireCurrentPeer(n,t),this.options.secret&&(this.localFingerprint=p(a)),r.send({kind:`offer`,data:{type:`offer`,sdp:a}}),this.offerSent=!0;for(let e of this.localCandidates.splice(0))this.sendCandidate(e)}remoteFingerprintAlgorithm(e,t){if(!this.options.secret)return;let n=t.sdp;try{if(typeof n!=`string`)throw Error(`answer carries no SDP`);return m(n).algorithm}catch{this.failPairing(e);return}}failPairing(e){e.close(),this.options.onPairingFailed?.()}awaitVerifiedCertificate(e,t,n,r,i){this.stopAwaitingCertificate=S(e,r,e=>{if(i!==this.generation)return;if(t.readyState===`open`){this.startPairing(t,n,e,i);return}let r=t.onStateChange(a=>{a===`open`&&i===this.generation&&(r(),this.startPairing(t,n,e,i))})},()=>{i===this.generation&&this.failPairing(t)})}startPairing(e,t,n,r){let i=this.options.secret;if(!i||!this.localFingerprint)return;this.pairingGate=new Ue({cryptoContext:this.options.cryptoContext,channel:{send:t=>e.send(t),close:()=>e.close()},session:t,secret:i,role:`initiator`,localFingerprint:this.localFingerprint,remoteFingerprint:n,onAccept:e=>{r===this.generation&&(this.deliveryLifecycle.accept(r),this.options.onPaired?.(e))},...this.options.onPairingFailed?{onReject:this.options.onPairingFailed}:{},...this.options.reconnect?{reconnect:this.options.reconnect}:{},...this.options.localPeer?{localPeer:this.options.localPeer}:{},...this.options.connectionApproval?{connectionApproval:this.options.connectionApproval}:{},...this.options.resumeBridge?{resumeBridge:this.options.resumeBridge}:{},...this.options.personalUsageReporter?{personalUsageReporter:this.options.personalUsageReporter}:{},...this.options.usageReporter?{usageReporter:this.options.usageReporter}:{},...this.options.storedSessionUsageReporter?{storedSessionUsageReporter:this.options.storedSessionUsageReporter}:{},surface:`remote`,commandSurfaceLocality:`remote`,onDeliveryError:(t,n)=>this.deliveryLifecycle.handleFailure(e,r,t,n)});let a=this.pairingGate;for(let e of this.pendingFrames.splice(0))a.onInbound(e)}wireChannel(e,n,i){if(this.options.secret){e.onMessage(e=>{i===this.generation&&(this.pairingGate?this.pairingGate.onInbound(e):this.pendingFrames.length<16&&this.pendingFrames.push(e))}),e.onStateChange(e=>{i===this.generation&&e===`closed`&&(this.pairingGate?.onChannelClosed(),this.deliveryLifecycle.handleDrop(i))}),this.cleanupHandler=()=>this.pairingGate?.cleanup();return}let{onMessage:a,cleanup:o}=r({session:n,deliver:ve(e,(t,n)=>this.deliveryLifecycle.handleFailure(e,i,t,n)),...this.options.personalUsageReporter?{personalUsageReporter:this.options.personalUsageReporter}:{},...this.options.usageReporter?{usageReporter:this.options.usageReporter}:{},...this.options.storedSessionUsageReporter?{storedSessionUsageReporter:this.options.storedSessionUsageReporter}:{},surface:`remote`,commandSurfaceLocality:`remote`,maxFrameBytes:t});this.cleanupHandler=o,e.onMessage(e=>{i===this.generation&&a(e)})}async stop(){this.generation+=1,this.cleanupHandler?.(),this.unsubscribeSignal?.(),this.cleanupHandler=void 0,this.unsubscribeSignal=void 0,this.pairingGate=void 0,this.localFingerprint=void 0,this.answered=!1,this.offerSent=!1,this.localCandidates=[],this.pendingFrames=[],this.stopAwaitingCertificate?.(),this.stopAwaitingCertificate=void 0,this.deliveryLifecycle.reset(this.generation),this.peer&&=(this.peer.close(),void 0),this.session=void 0}};function qe(e){if(typeof e!=`object`||!e)return;let t=e;if(typeof t.candidate!=`string`||t.candidate.length===0)return;let n=typeof t.sdpMid==`string`?t.sdpMid:typeof t.sdpMLineIndex==`number`?String(t.sdpMLineIndex):`0`;return{candidate:t.candidate,mid:n}}function Je(){let e=[],t=[],n=!0;function r(e,t){return{send(e){n&&queueMicrotask(()=>{for(let n of t)n(e)})},onSignal(t){return e.push(t),()=>{let n=e.indexOf(t);n>=0&&e.splice(n,1)}},close(){n=!1,e.length=0}}}return[r(e,t),r(t,e)]}const Ye=new Set([`offer`,`answer`,`ice`]);function Xe(e){return new g(e)}var Ze=class{options;socket;handlers=[];outbox=[];joined=!1;closed=!1;constructor(e){this.options=e;let t=e.createSocket??Xe;this.socket=t(e.url),this.socket.on(`open`,()=>this.handleOpen()),this.socket.on(`message`,e=>this.handleMessage(e)),this.socket.on(`error`,e=>this.fail(e instanceof Error?e:Error(String(e)))),this.socket.on(`close`,()=>this.handleClose())}handleOpen(){this.socket.send(JSON.stringify({type:`join`,rendezvous:this.options.rendezvous}));for(let e of this.outbox)this.writeSignal(e);this.outbox.length=0}handleMessage(e){let t;try{t=JSON.parse(typeof e==`string`?e:String(e))}catch{return}if(typeof t!=`object`||!t)return;let n=t;if(n.type===`joined`){this.joined=!0,this.options.onReady?.();return}if(n.type===`error`){this.fail(Error(`signaling relay rejected the connection: ${String(n.reason)}`));return}if(n.type===`signal`&&typeof n.kind==`string`&&Ye.has(n.kind)){let e={kind:n.kind,data:n.data};for(let t of this.handlers)t(e)}}handleClose(){this.closed||this.joined||this.fail(Error(`signaling socket closed before the rendezvous was joined`))}fail(e){this.options.onError?.(e)}writeSignal(e){this.socket.send(JSON.stringify({type:`signal`,kind:e.kind,data:e.data}))}send(e){this.closed||(this.socket.readyState===1?this.writeSignal(e):this.outbox.push(e))}onSignal(e){return this.handlers.push(e),()=>{let t=this.handlers.indexOf(e);t>=0&&this.handlers.splice(t,1)}}close(){this.closed=!0,this.handlers.length=0,this.outbox.length=0,this.socket.close()}};const Qe=/^[A-Za-z0-9_-]{22}$/,$e=6e4;function O(e){return typeof e==`string`&&Qe.test(e)}function k(e,t){return typeof e==`string`&&e.length>0&&e.length<=t}function et(e){if(typeof e!=`object`||!e||Array.isArray(e))return;let t=e;if(!(t.v!==1||!O(t.from))){if(t.kind===`hello`)return{v:1,kind:`hello`,from:t.from};if(!(!O(t.to)||!O(t.cid))){if(t.kind===`offer`||t.kind===`answer`)return k(t.sdp,49152)?{v:1,kind:t.kind,from:t.from,to:t.to,cid:t.cid,sdp:t.sdp}:void 0;if(t.kind===`ice`){let e=t.candidate;if(typeof e!=`object`||!e||Array.isArray(e))return;let n=e;return!k(n.candidate,2048)||n.sdpMid!==void 0&&!k(n.sdpMid,64)||n.sdpMLineIndex!==void 0&&!(typeof n.sdpMLineIndex==`number`&&Number.isInteger(n.sdpMLineIndex)&&n.sdpMLineIndex>=0&&n.sdpMLineIndex<64)?void 0:{v:1,kind:`ice`,from:t.from,to:t.to,cid:t.cid,candidate:{candidate:n.candidate,...n.sdpMid===void 0?{}:{sdpMid:n.sdpMid},...n.sdpMLineIndex===void 0?{}:{sdpMLineIndex:n.sdpMLineIndex}}}}}}}function tt(e){if(typeof e!=`object`||!e||Array.isArray(e))return;let t=e;if(!(t.t!==`mesh-msg`||typeof t.body!=`string`||t.body.length>6e4))return{t:`mesh-msg`,body:t.body}}var nt=class extends Error{end;stage;role;peer;channelClose;cause;constructor(e){let t=[`mesh link ended (${e.end}) during ${e.stage} as ${e.role}`];e.detail!==void 0&&t.push(e.detail),e.cause!==void 0&&t.push(e.cause instanceof Error?e.cause.message:String(e.cause));let n=e.peer;n!==void 0&&t.push(`connection ${n.state} [${n.history.join(` > `)}], ice ${n.ice??`?`}, gathering ${n.gathering??`?`}, candidates ${n.localCandidates} sent / ${n.remoteCandidates} applied, closed by ${n.closedBy??`the peer or the network`}${n.handlerError===void 0?``:` (${n.handlerError})`}`),e.channelClose!==void 0&&t.push(`channel ${e.channelClose}`),super(t.join(`; `)),this.name=`MeshLinkEndedError`,this.end=e.end,this.stage=e.stage,this.role=e.role,n!==void 0&&(this.peer=n),e.channelClose!==void 0&&(this.channelClose=e.channelClose),e.cause!==void 0&&(this.cause=e.cause)}};const rt=`agent-file`,it=JSON.stringify({t:`mesh-admitted`});var at=class{options;state=`connecting`;peer;channel;localFingerprint;remoteFingerprint;tookRemoteDescription=!1;creatingPeer=!1;sentDescription=!1;localCandidates=[];remoteCandidates=0;handshake;fedProof=!1;held=[];handlers=new Set;endHandlers=new Set;fileChannels=new Set;fileHandlers=new Set;signalChain=Promise.resolve();stopAwaitingCertificate;timer;admissionResult;constructor(e){this.options=e,this.timer=setTimeout(()=>this.end(`timeout`),e.connectTimeoutMs)}get role(){return this.options.role}get admitted(){return this.state===`admitted`}get ended(){return this.isEnded()}isEnded(){return this.state===`ended`}get admission(){return this.state===`admitted`?this.admissionResult:void 0}get channelBinding(){if(this.state===`admitted`&&this.localFingerprint!==void 0&&this.remoteFingerprint!==void 0)return{localFingerprint:this.localFingerprint,remoteFingerprint:this.remoteFingerprint}}async offer(){if(!(this.options.role!==`offerer`||this.creatingPeer||this.isEnded())){this.creatingPeer=!0;try{let e=await this.createPeer();if(e===void 0)return;this.adoptChannel(e.createDataChannel(`agent-mesh`));let t=await e.createOffer();if(this.isEnded())return;this.localFingerprint=p(t),this.sendDescription({kind:`offer`,sdp:t})}catch(e){this.end(`signaling`,e)}}}onSignal(e){this.isEnded()||(this.signalChain=this.signalChain.then(()=>this.applySignal(e)).catch(e=>this.end(`signaling`,e)))}async applySignal(e){if(this.isEnded())return;if(e.kind===`ice`){if(!this.tookRemoteDescription||!this.peer||++this.remoteCandidates>64)return;this.peer.addRemoteCandidate({candidate:e.candidate.candidate,mid:e.candidate.sdpMid??String(e.candidate.sdpMLineIndex??0)});return}let t=this.options.role===`offerer`?`answer`:`offer`;if(e.kind!==t||this.tookRemoteDescription)return;this.tookRemoteDescription=!0;let n;try{n=m(e.sdp).algorithm}catch(e){this.end(`channel-binding`,e);return}if(this.options.role===`offerer`){let t=this.peer;if(!t)return;t.acceptAnswer(e.sdp),this.awaitCertificate(t,n);return}let r=await this.createPeer();if(r===void 0)return;let i=await r.acceptOffer(e.sdp);this.isEnded()||(this.localFingerprint=p(i),this.sendDescription({kind:`answer`,sdp:i}),this.awaitCertificate(r,n))}async createPeer(){let e=await this.options.createPeer();if(this.isEnded()){e.close();return}return this.peer=e,e.onLocalCandidate(e=>{if(this.isEnded())return;let t={kind:`ice`,candidate:{candidate:e.candidate,sdpMid:e.mid}};this.sentDescription?this.options.sendSignal(t):this.localCandidates.length<64&&this.localCandidates.push(t)}),e.onStateChange(e=>{(e===`failed`||e===`closed`)&&this.end(`closed`,void 0,`connection ${e}`)}),e.onDataChannel(e=>this.incomingChannel(e)),e}incomingChannel(e){if(this.options.role===`answerer`&&this.channel===void 0&&!this.isEnded()){this.adoptChannel(e);return}if(this.state!==`admitted`||e.label!==rt||this.fileHandlers.size===0||this.fileChannels.size>=4){e.close();return}this.trackFileChannel(e);for(let t of this.fileHandlers)t(e)}trackFileChannel(e){this.fileChannels.add(e),e.onStateChange(t=>{t===`closed`&&this.fileChannels.delete(e)})}openFileChannel(){let e=this.peer;if(this.state!==`admitted`||e===void 0)return Promise.reject(Error(`mesh link is not admitted`));if(this.fileChannels.size>=4)return Promise.reject(Error(`too many file transfers are open on this link`));let t=e.createDataChannel(rt);return this.trackFileChannel(t),new Promise((e,n)=>{if(t.readyState===`open`){e(t);return}let r=setTimeout(()=>{i(),t.close(),n(Error(`the file channel did not open`))},1e4),i=t.onStateChange(a=>{a!==`connecting`&&(clearTimeout(r),i(),a===`open`?e(t):n(Error(`the file channel closed before it opened`)))})})}onFileChannel(e){return this.fileHandlers.add(e),()=>this.fileHandlers.delete(e)}sendDescription(e){this.options.sendSignal(e),this.sentDescription=!0;for(let e of this.localCandidates.splice(0))this.options.sendSignal(e)}awaitCertificate(e,t){this.stopAwaitingCertificate=S(e,t,e=>{this.isEnded()||(this.remoteFingerprint=e,this.maybeStartHandshake())},e=>this.end(`channel-binding`,Error(e)))}adoptChannel(e){this.channel=e,e.onMessage(e=>this.inbound(e)),e.onStateChange(e=>{e===`open`?this.maybeStartHandshake():e===`closed`&&this.end(`closed`,void 0,`data channel closed`)}),e.readyState===`open`&&this.maybeStartHandshake()}maybeStartHandshake(){let e=this.channel;if(this.state!==`connecting`||this.handshake!==void 0||e===void 0||this.localFingerprint===void 0||this.remoteFingerprint===void 0||e.readyState!==`open`)return;let t;try{t=this.options.startHandshake({localFingerprint:this.localFingerprint,remoteFingerprint:this.remoteFingerprint,send:e=>this.write(JSON.stringify(e))})}catch(e){this.end(`handshake`,e);return}this.handshake=t,t.result.then(e=>this.confirm(e),e=>this.end(`handshake`,e));let n=this.held.splice(0);for(let e of n)this.feed(e)}inbound(e){if(!this.isEnded()){if(this.state===`admitted`){this.deliver(e);return}if(this.state===`confirming`){this.confirmed(e);return}if(this.handshake===void 0){this.hold(e);return}this.feed(e)}}hold(e){if(this.held.length>=16){this.end(`protocol`);return}this.held.push(e)}feed(e){if(this.fedProof){this.hold(e);return}let t;try{t=JSON.parse(e)}catch{t=e}typeof t==`object`&&t&&t.t===`dh-prove`&&(this.fedProof=!0),this.handshake?.onFrame(t)}confirm(e){if(this.state!==`connecting`)return;if(this.options.accepts!==void 0&&!this.options.accepts(e)){this.end(`handshake`,Error(`the admitted device is not the one this link is for`));return}this.state=`confirming`,this.admissionResult=e,this.write(it);let t=this.held.splice(0);for(let e of t)this.inbound(e)}confirmed(e){let t;try{t=JSON.parse(e)}catch{t=void 0}let n=this.admissionResult;if(n===void 0||typeof t!=`object`||!t||t.t!==`mesh-admitted`){this.end(`protocol`);return}clearTimeout(this.timer),this.state=`admitted`,this.options.onAdmitted(n)}deliver(e){let t;try{t=JSON.parse(e)}catch{t=void 0}let n=tt(t);if(n===void 0){this.end(`protocol`);return}for(let e of this.handlers)e(n.body)}write(e){try{this.channel?.send(e)}catch(e){this.end(`closed`,e)}}send(e){if(this.state!==`admitted`)throw Error(`mesh link is not admitted`);if(e.length>6e4)throw Error(`mesh message exceeds ${$e} characters`);this.write(JSON.stringify({t:`mesh-msg`,body:e}))}onMessage(e){return this.handlers.add(e),()=>this.handlers.delete(e)}onEnd(e){return this.endHandlers.add(e),()=>this.endHandlers.delete(e)}close(){this.end(`closed`,void 0,`closed by this side`)}get stage(){return this.state===`admitted`||this.state===`confirming`?this.state:this.handshake===void 0?this.remoteFingerprint===void 0?this.tookRemoteDescription?`connecting`:`signaling`:`awaiting-channel`:`handshake`}end(e,t,n){if(this.isEnded())return;let r=new nt({end:e,stage:this.stage,role:this.options.role,...n===void 0?{}:{detail:n},...this.peer===void 0?{}:{peer:this.peer.diagnostics()},...this.channel?.closeCause===void 0?{}:{channelClose:this.channel.closeCause},...t===void 0?{}:{cause:t}});this.state=`ended`,clearTimeout(this.timer),this.stopAwaitingCertificate?.(),this.held.length=0,this.handshake?.onFrame(void 0),this.channel?.close();for(let e of this.fileChannels)e.close();this.fileChannels.clear(),this.fileHandlers.clear();let i=this.peer;i&&setTimeout(()=>i.close(),250).unref?.(),this.options.onEnded(e,r);for(let t of this.endHandlers)t(e);this.endHandlers.clear(),this.handlers.clear()}};const A=554869826,j={Binding:1,Allocate:3,Refresh:4,Send:6,Data:7,CreatePermission:8,ChannelBind:9},M={Request:0,Indication:1,Success:2,Error:3},N={MappedAddress:1,Username:6,MessageIntegrity:8,ErrorCode:9,UnknownAttributes:10,ChannelNumber:12,Lifetime:13,XorPeerAddress:18,Data:19,Realm:20,Nonce:21,XorRelayedAddress:22,RequestedAddressFamily:23,EvenPort:24,RequestedTransport:25,DontFragment:26,MessageIntegritySha256:28,PasswordAlgorithm:29,Userhash:30,XorMappedAddress:32,ReservationToken:34,Priority:36,UseCandidate:37,Fingerprint:32808};function ot(e,t){return e&15|(e&112)<<1|(e&3968)<<2|(t&1)<<4|(t&2)<<7}function st(e){return e.length>=20&&(e[0]&192)==0&&e.readUInt32BE(4)===554869826}function ct(e){if(!st(e))return;let t=e.readUInt16BE(0),n=e.readUInt16BE(2);if(n%4!=0||20+n>e.length)return;let r=t&15|(t&224)>>1|(t&15872)>>2,i=(t&16)>>4|(t&256)>>7,a=[],o=20,s=20+n;for(;o<s;){if(o+4>s)return;let t=e.readUInt16BE(o),n=e.readUInt16BE(o+2);if(o+4+n>s)return;a.push({type:t,value:e.subarray(o+4,o+4+n),offset:o}),o+=4+n+(4-n%4)%4}if(o===s)return{method:r,cls:i,transactionId:Buffer.from(e.subarray(8,20)),attributes:a,raw:e.subarray(0,s)}}function P(e,t){return e.attributes.find(e=>e.type===t)?.value}function lt(e,t){return e.attributes.filter(e=>e.type===t).map(e=>e.value)}function ut(e){let t=e.attributes.findIndex(e=>e.type===N.MessageIntegrity);return t<0?e:{...e,attributes:e.attributes.slice(0,t+1)}}function dt(e,t){if(e.length<8)return;let n=e[1],r=e.readUInt16BE(2)^A>>>16;if(n===1&&e.length===8){let t=e.readUInt32BE(4)^A;return{address:[t>>>24,t>>>16&255,t>>>8&255,t&255].join(`.`),port:r}}if(n===2&&e.length===20){let n=Buffer.alloc(16);n.writeUInt32BE(A,0),t.copy(n,4);let i=[];for(let t=0;t<16;t+=2)i.push(((e.readUInt16BE(4+t)^n.readUInt16BE(t))&65535).toString(16));return{address:i.join(`:`),port:r}}}function ft(e){let[t=``,n=``]=e.split(`::`),r=t.length>0?t.split(`:`):[],i=e.includes(`::`)&&n.length>0?n.split(`:`):[],a=e.includes(`::`)?[...r,...Array(8-r.length-i.length).fill(`0`),...i]:r,o=Buffer.alloc(16);return a.forEach((e,t)=>o.writeUInt16BE(parseInt(e,16)&65535,t*2)),o}function F(e,t){let n=(e.port^A>>>16)&65535;if(b(e.address)){let t=Buffer.alloc(8);t[1]=1,t.writeUInt16BE(n,2);let r=e.address.split(`.`).reduce((e,t)=>e<<8|Number(t),0);return t.writeUInt32BE((r^A)>>>0,4),t}if(!pe(e.address))throw Error(`not an IP address: ${e.address}`);let r=Buffer.alloc(20);r[1]=2,r.writeUInt16BE(n,2);let i=Buffer.alloc(16);i.writeUInt32BE(A,0),t.copy(i,4);let a=ft(e.address);for(let e=0;e<16;e+=1)r[4+e]=a[e]^i[e];return r}function pt(e,t,n){return _(`md5`).update(`${e}:${t}:${n}`,`utf8`).digest()}function mt(e,t){let n=e.attributes.find(e=>e.type===N.MessageIntegrity);if(n===void 0||n.value.length!==20)return!1;let r=Buffer.from(e.raw.subarray(0,n.offset));return r.writeUInt16BE(n.offset-20+24,2),y(v(`sha1`,t).update(r).digest(),n.value)}const ht=(()=>{let e=new Uint32Array(256);for(let t=0;t<256;t+=1){let n=t;for(let e=0;e<8;e+=1)n=n&1?3988292384^n>>>1:n>>>1;e[t]=n>>>0}return e})();function gt(e){let t=4294967295;for(let n of e)t=ht[(t^n)&255]^t>>>8;return(t^4294967295)>>>0}function I(e,t,n,r,i={}){let a=[],o=Buffer.alloc(20);o.writeUInt16BE(ot(e,t),0),o.writeUInt32BE(A,4),n.copy(o,8,0,12),a.push(o);let s=(e,t)=>{let n=Buffer.alloc(4);n.writeUInt16BE(e,0),n.writeUInt16BE(t.length,2),a.push(n,t,Buffer.alloc((4-t.length%4)%4))};for(let e of r)s(e.type,e.value);let c=()=>Buffer.concat(a);if(i.integrityKey!==void 0){let e=c();e.writeUInt16BE(e.length-20+24,2),s(N.MessageIntegrity,v(`sha1`,i.integrityKey).update(e).digest())}if(i.fingerprint!==!1){let e=c();e.writeUInt16BE(e.length-20+8,2);let t=Buffer.alloc(4);t.writeUInt32BE((gt(e)^1398035790)>>>0,0),s(N.Fingerprint,t)}let l=c();if(l.writeUInt16BE(l.length-20,2),l.length>65535)throw Error(`STUN message too large`);return l}function _t(e,t){let n=Buffer.from(t,`utf8`),r=Buffer.alloc(4+n.length);return r[2]=Math.floor(e/100),r[3]=e%100,n.copy(r,4),r}function L(e){let t=Buffer.alloc(4);return t.writeUInt32BE(e>>>0,0),t}function vt(e){return e.length>=4&&(e[0]&192)==64}function yt(e){if(!vt(e))return;let t=e.readUInt16BE(0),n=e.readUInt16BE(2);if(!(4+n>e.length))return{channel:t,payload:e.subarray(4,4+n)}}function bt(e,t){let n=Buffer.alloc(4);return n.writeUInt16BE(e,0),n.writeUInt16BE(t.length,2),Buffer.concat([n,t,Buffer.alloc((4-t.length%4)%4)])}const xt={allocationsPerOwner:8,totalAllocations:64,bytesPerSecondPerOwner:1024*1024,maxLifetimeSeconds:3600,maxAllocationAgeMs:720*60*1e3,permissionsPerAllocation:32,channelsPerAllocation:32},St={perSourcePerSecond:10,totalPerSecond:2e3},Ct=3e5,wt=new Set([N.MappedAddress,N.Username,N.MessageIntegrity,N.ErrorCode,N.ChannelNumber,N.Lifetime,N.XorPeerAddress,N.Data,N.Realm,N.Nonce,N.RequestedAddressFamily,N.RequestedTransport,N.MessageIntegritySha256,N.PasswordAlgorithm,N.XorMappedAddress,N.Priority,N.UseCandidate]);function R(e){return`${e.address}:${e.port}`}function Tt(){for(let e of Object.values(x()))for(let t of e??[])if(t.family===`IPv4`&&!t.internal)return t.address;return`127.0.0.1`}function Et(e){return e.startsWith(`127.`)||e===`::1`}function Dt(e){let[t=0,n=0]=e.split(`.`).map(Number);return t===10||t===172&&n>=16&&n<=31||t===192&&n===168||t===169&&n===254||t===100&&n>=64&&n<=127}function Ot(e,t){return n=>{if(!b(n))return!1;let r=Number(n.split(`.`)[0]);return r===0||r>=224?!1:r===127?e:t||!Dt(n)}}async function kt(e,t){let n=fe(`udp4`);try{return await new Promise((r,i)=>{n.once(`error`,i),n.bind(e,t,()=>{n.off(`error`,i),r()})}),n}catch(e){try{n.close()}catch{}throw e}}async function At(e,t){try{return await kt(e,t)}catch{return}}function jt(e,t,n){let r=e instanceof Error?e.code:void 0,i=r===`EADDRINUSE`?`the port is taken`:r===`EADDRNOTAVAIL`?`${t} is not an address of this machine`:r===`EACCES`?`port ${n} needs privileges this process does not have`:Nt(e).message;return Error(`the TURN relay cannot listen on UDP ${t}:${n}: ${i}`,{cause:e})}function Mt(){let e=new Set;for(let t of Object.values(x()))for(let n of t??[])e.add(n.address);return e}function z(e,t,n,r=1){let i=Math.max(0,n-e.at);return e.tokens=Math.min(Math.max(t,r),e.tokens+i/1e3*t),e.at=n,e.tokens>=r}function Nt(e){return e instanceof Error?e:Error(String(e))}var Pt=class e{socket;options;bindHost;relayAddress;allocations=new Map;buckets=new Map;quotas;realm;limits;answerBuckets=new Map;answerBudget;nonceSecret=le(32);ownAddresses=Mt();allowPeer;sweeper;retained;closed=!1;constructor(e,t,n,r){this.socket=e,this.options=t,this.bindHost=n,this.relayAddress=r,this.quotas={...xt,...t.quotas},this.realm=t.realm??`r`,this.limits={...St,...t.unauthenticatedLimits},this.allowPeer=t.allowPeer??Ot(Et(r),t.allowPrivatePeers??!0),e.on(`message`,(e,t)=>this.receive(e,t)),e.on(`error`,e=>t.onError?.(e)),this.sweeper=setInterval(()=>this.sweep(),5e3),this.sweeper.unref?.()}static async start(t){let n=Buffer.byteLength(t.realm??`r`);if(n===0||n>4)throw Error(`TURN realm must be 1 to 4 bytes`);let r=t.host??`0.0.0.0`,i=t.port??3478,a;try{a=await kt(i,r)}catch(e){throw jt(e,r,i)}let o=t.relayAddress??(r===`0.0.0.0`?Tt():r);return new e(a,t,r,o)}get address(){let e=this.socket.address();return{address:this.bindHost===`0.0.0.0`?this.relayAddress:e.address,port:e.port}}allocationCount(e){if(e===void 0)return this.allocations.size;let t=0;for(let n of this.allocations.values())n.owner===e&&(t+=1);return t}get unauthenticatedSourceCount(){return this.answerBuckets.size}retain(e){this.retained=new Set(e);for(let t of[...this.allocations.values()])e.has(t.owner)||this.remove(t);for(let t of[...this.buckets.keys()])e.has(t)||this.buckets.delete(t)}close(){if(this.closed)return Promise.resolve();this.closed=!0,clearInterval(this.sweeper);for(let e of[...this.allocations.values()])this.remove(e);return new Promise(e=>this.socket.close(()=>e()))}now(){return(this.options.now??Date.now)()}receive(e,t){if(this.closed)return;if(vt(e)){this.fromClientChannel(e,t);return}let n=ct(e);if(n!==void 0){if(n.cls===M.Indication){n.method===j.Send&&this.fromClientSend(n,t);return}n.cls===M.Request&&this.request(n,t).catch(e=>this.options.onError?.(Nt(e)))}}send(e,t){this.closed||this.socket.send(e,t.port,t.address,e=>{e&&this.options.onError?.(e)})}reply(e,t,n,r){let i=I(e.method,M.Success,e.transactionId,n,{...r===void 0?{}:{integrityKey:r}});return this.send(i,t),i}fail(e,t,n,r,i=[],a){let o=I(e.method,M.Error,e.transactionId,[{type:N.ErrorCode,value:_t(n,r)},...i],{...a===void 0?{}:{integrityKey:a}});this.send(o,t)}nonce(e){let t=Buffer.alloc(4);return t.writeUInt32BE(Math.floor(this.now()/1e3)>>>0,0),Buffer.concat([t,this.nonceMac(t,e)]).toString(`base64url`)}nonceMac(e,t){return v(`sha256`,this.nonceSecret).update(e).update(R(t)).digest().subarray(0,8)}nonceValid(e,t){if(!/^[A-Za-z0-9_-]{16}$/.test(e))return!1;let n=Buffer.from(e,`base64url`),r=n.subarray(0,4);if(!y(n.subarray(4),this.nonceMac(r,t)))return!1;let i=this.now()-r.readUInt32BE(0)*1e3;return i>=-6e4&&i<=6e5}answerUnauthenticated(e,t,n,r,i){let a=this.now();if(e.raw.length<r)return;let o=this.answerBuckets.get(t.address),s=o??{tokens:this.limits.perSourcePerSecond,at:a};if(!z(s,this.limits.perSourcePerSecond,a))return;let c=this.answerBudget??={tokens:this.limits.totalPerSecond,at:a};if(!z(c,this.limits.totalPerSecond,a))return;--c.tokens;let l=I(e.method,n,e.transactionId,i(),{fingerprint:!1});l.length>e.raw.length||(o===void 0&&this.answerBuckets.set(t.address,s),--s.tokens,this.send(l,t))}refuseUnauthenticated(e,t,n,r=0,i=()=>[]){this.answerUnauthenticated(e,t,M.Error,28+r,()=>[{type:N.ErrorCode,value:_t(n,``)},...i()])}challenge(e,t,n){let r=Math.ceil(Buffer.byteLength(this.realm)/4)*4;this.refuseUnauthenticated(e,t,n,4+r+4+16,()=>[{type:N.Realm,value:Buffer.from(this.realm)},{type:N.Nonce,value:Buffer.from(this.nonce(t))}])}async authenticate(e,t,n){if(P(e,N.MessageIntegrity)===void 0){this.challenge(e,t,401);return}let r=P(e,N.Username)?.toString(`utf8`),i=P(e,N.Realm)?.toString(`utf8`),a=P(e,N.Nonce)?.toString(`utf8`);if(r===void 0||i===void 0||a===void 0){this.refuseUnauthenticated(e,t,400);return}if(i!==this.realm){this.challenge(e,t,401);return}if(!this.nonceValid(a,t)){this.challenge(e,t,438);return}if(n!==void 0){if(r!==n.username){this.refuseUnauthenticated(e,t,441);return}if(!mt(e,n.integrityKey)){this.challenge(e,t,401);return}return{auth:{owner:n.owner,password:``},key:n.integrityKey,username:r}}let o;try{o=await this.options.authorize(r)}catch{o=void 0}if(this.closed)return;let s=o===void 0?void 0:pt(r,this.realm,o.password);if(o===void 0||s===void 0||!mt(e,s)){this.challenge(e,t,401);return}return{auth:o,key:s,username:r}}unknownAttributes(e){return e.attributes.map(e=>e.type).filter(e=>e<32768&&!wt.has(e))}async request(e,t){let n={address:t.address,port:t.port};if(e.method===j.Binding){let t=b(n.address)?8:20;this.answerUnauthenticated(e,n,M.Success,24+t,()=>[{type:N.XorMappedAddress,value:F(n,e.transactionId)}]);return}if(![j.Allocate,j.Refresh,j.CreatePermission,j.ChannelBind].includes(e.method)){this.refuseUnauthenticated(e,n,400);return}let r=this.allocations.get(R(n)),i=this.live(r)?r:void 0;if(e.method===j.Allocate&&i!==void 0&&i.transactionId.equals(e.transactionId)){i.response.length<=e.raw.length&&this.send(i.response,n);return}let a=await this.authenticate(e,n,i);a!==void 0&&await this.authenticatedRequest(ut(e),n,a)}async authenticatedRequest(e,t,n){let{key:r}=n,i=this.unknownAttributes(e);if(i.length>0){let n=Buffer.alloc(i.length*2);i.forEach((e,t)=>n.writeUInt16BE(e,t*2)),this.fail(e,t,420,`Unknown Attribute`,[{type:N.UnknownAttributes,value:n}],r);return}let a=this.allocations.get(R(t)),o=this.live(a)?a:void 0;if(e.method===j.Allocate){await this.allocate(e,t,n,o);return}if(o===void 0||o.owner!==n.auth.owner){this.fail(e,t,437,`Allocation Mismatch`,[],r);return}e.method===j.Refresh?this.refresh(e,t,o):e.method===j.CreatePermission?this.permit(e,t,o):this.bindChannel(e,t,o)}async allocate(e,t,n,r){let{auth:i,key:a,username:o}=n;if(r!==void 0){this.fail(e,t,437,`Allocation Mismatch`,[],a);return}let s=P(e,N.RequestedTransport);if(s===void 0||s.length!==4){this.fail(e,t,400,`Bad Request`,[],a);return}if(s[0]!==17){this.fail(e,t,442,`Unsupported Transport Protocol`,[],a);return}let c=P(e,N.RequestedAddressFamily);if(c!==void 0&&c[0]!==1){this.fail(e,t,440,`Address Family not Supported`,[],a);return}if(this.retained!==void 0&&!this.retained.has(i.owner)){this.fail(e,t,403,`Forbidden`,[],a);return}if(this.allocations.size>=this.quotas.totalAllocations){this.fail(e,t,508,`Insufficient Capacity`,[],a);return}if(this.allocationCount(i.owner)>=this.quotas.allocationsPerOwner){this.fail(e,t,486,`Allocation Quota Reached`,[],a);return}let l=await this.relayedSocket();if(l===void 0){this.fail(e,t,508,`Insufficient Capacity`,[],a);return}if(!this.closed&&this.retained!==void 0&&!this.retained.has(i.owner)){l.close(),this.fail(e,t,403,`Forbidden`,[],a);return}if(this.closed||this.allocations.has(R(t))||this.allocationCount(i.owner)>=this.quotas.allocationsPerOwner||this.allocations.size>=this.quotas.totalAllocations){l.close(),this.closed||this.fail(e,t,486,`Allocation Quota Reached`,[],a);return}let u=this.now(),d=this.grantedLifetime(e,u,u),f={key:R(t),client:t,owner:i.owner,username:o,integrityKey:a,transactionId:Buffer.from(e.transactionId),socket:l,relayed:{address:this.relayAddress,port:l.address().port},createdAt:u,expiresAt:u+d*1e3,permissions:new Map,channelsByNumber:new Map,channelsByPeer:new Map,response:Buffer.alloc(0)};l.on(`message`,(e,t)=>this.fromPeer(f,e,t)),l.on(`error`,e=>this.options.onError?.(e)),this.allocations.set(f.key,f),f.response=this.reply(e,t,[{type:N.XorRelayedAddress,value:F(f.relayed,e.transactionId)},{type:N.Lifetime,value:L(d)},{type:N.XorMappedAddress,value:F(t,e.transactionId)}],a)}async relayedSocket(){let e=this.options.relayPorts;if(e===void 0)return At(0,this.bindHost);let t=e.max-e.min+1;for(let n=0;n<Math.min(t,8);n+=1){let t=await At(ue(e.min,e.max+1),this.bindHost);if(t!==void 0)return t}let n=new Set(this.allocationPorts());for(let t=e.min;t<=e.max;t+=1){if(n.has(t))continue;let e=await At(t,this.bindHost);if(e!==void 0)return e}}allocationPorts(){return[...this.allocations.values()].map(e=>e.relayed.port)}isServerItself(e){return e.port===this.socket.address().port&&(Et(e.address)||e.address===this.relayAddress||e.address===this.bindHost||this.bindHost===`0.0.0.0`&&this.ownAddresses.has(e.address))}grantedLifetime(e,t,n){let r=P(e,N.Lifetime),i=r!==void 0&&r.length===4?r.readUInt32BE(0):600,a=Math.floor((t+this.quotas.maxAllocationAgeMs-n)/1e3);return Math.max(0,Math.min(i,this.quotas.maxLifetimeSeconds,a))}refresh(e,t,n){let r=this.now(),i=this.grantedLifetime(e,n.createdAt,r);if(i===0){this.remove(n),this.reply(e,t,[{type:N.Lifetime,value:L(0)}],n.integrityKey);return}n.expiresAt=r+i*1e3,this.reply(e,t,[{type:N.Lifetime,value:L(i)}],n.integrityKey)}peerAddresses(e){let t=[];for(let n of lt(e,N.XorPeerAddress)){let r=dt(n,e.transactionId);if(r===void 0)return;t.push(r)}return t.length>0?t:void 0}permit(e,t,n){let r=n.integrityKey,i=this.peerAddresses(e);if(i===void 0){this.fail(e,t,400,`Bad Request`,[],r);return}if(i.some(e=>!b(e.address))){this.fail(e,t,443,`Peer Address Family Mismatch`,[],r);return}if(i.some(e=>!this.allowPeer(e.address))){this.fail(e,t,403,`Forbidden`,[],r);return}let a=new Set(i.map(e=>e.address).filter(e=>!n.permissions.has(e)));if(n.permissions.size+a.size>this.quotas.permissionsPerAllocation){this.fail(e,t,508,`Insufficient Capacity`,[],r);return}let o=this.now()+Ct;for(let e of i)n.permissions.set(e.address,o);this.reply(e,t,[],r)}bindChannel(e,t,n){let r=n.integrityKey,i=P(e,N.ChannelNumber),a=this.peerAddresses(e),o=i!==void 0&&i.length===4?i.readUInt16BE(0):-1;if(o<16384||o>20479||a===void 0||a.length!==1){this.fail(e,t,400,`Bad Request`,[],r);return}let s=a[0];if(!b(s.address)){this.fail(e,t,443,`Peer Address Family Mismatch`,[],r);return}if(!this.allowPeer(s.address)){this.fail(e,t,403,`Forbidden`,[],r);return}let c=n.channelsByNumber.get(o),l=n.channelsByPeer.get(R(s));if(c!==void 0&&R(c.peer)!==R(s)||l!==void 0&&l.number!==o){this.fail(e,t,400,`Bad Request`,[],r);return}if(c===void 0&&n.channelsByNumber.size>=this.quotas.channelsPerAllocation||!n.permissions.has(s.address)&&n.permissions.size>=this.quotas.permissionsPerAllocation){this.fail(e,t,508,`Insufficient Capacity`,[],r);return}let u=this.now(),d=c??{number:o,peer:s,expiresAt:0};d.expiresAt=u+6e5,n.channelsByNumber.set(o,d),n.channelsByPeer.set(R(s),d),n.permissions.set(s.address,u+Ct),this.reply(e,t,[],r)}permitted(e,t){let n=e.permissions.get(t);return n!==void 0&&n>this.now()}spend(e,t){let n=this.now(),r=this.quotas.bytesPerSecondPerOwner,i=this.buckets.get(e)??{tokens:r,at:n};return this.buckets.set(e,i),z(i,r,n,t)?(i.tokens-=t,!0):!1}live(e){return e===void 0?!1:e.expiresAt>this.now()?!0:(this.remove(e),!1)}fromClientSend(e,t){let n=this.allocations.get(R(t));if(!this.live(n))return;let r=P(e,N.XorPeerAddress),i=P(e,N.Data);if(r===void 0||i===void 0)return;let a=dt(r,e.transactionId);a===void 0||!this.permitted(n,a.address)||this.isServerItself(a)||this.spend(n.owner,i.length)&&n.socket.send(i,a.port,a.address)}fromClientChannel(e,t){let n=this.allocations.get(R(t));if(!this.live(n))return;let r=yt(e);if(r===void 0)return;let i=n.channelsByNumber.get(r.channel);i===void 0||i.expiresAt<=this.now()||this.permitted(n,i.peer.address)&&(this.isServerItself(i.peer)||this.spend(n.owner,r.payload.length)&&n.socket.send(r.payload,i.peer.port,i.peer.address))}fromPeer(e,t,n){if(this.allocations.get(e.key)!==e||!this.live(e)||!this.permitted(e,n.address)||!this.spend(e.owner,t.length))return;let r=e.channelsByPeer.get(R(n));if(r!==void 0&&r.expiresAt>this.now()){this.send(bt(r.number,t),e.client);return}let i=le(12);this.send(I(j.Data,M.Indication,i,[{type:N.XorPeerAddress,value:F({address:n.address,port:n.port},i)},{type:N.Data,value:t}]),e.client)}remove(e){this.allocations.get(e.key)===e&&this.allocations.delete(e.key);try{e.socket.close()}catch{}}sweep(){let e=this.now();for(let[t,n]of this.answerBuckets)Math.abs(e-n.at)>=1e3&&this.answerBuckets.delete(t);for(let t of[...this.allocations.values()]){if(t.expiresAt<=e){this.remove(t);continue}for(let[n,r]of t.permissions)r<=e&&t.permissions.delete(n);for(let[n,r]of t.channelsByNumber)r.expiresAt>e||(t.channelsByNumber.delete(n),t.channelsByPeer.delete(R(r.peer)))}}};const Ft=600*1e3,It=3600*1e3,Lt=/^(\d{1,12}):([A-Za-z0-9_-]{22})$/;function Rt(e){return Buffer.from(e).toString(`base64url`)}async function zt(e,t,n=Ft){let r=Math.min(Math.max(n,1e3),It),i=(await e.tag(`relay-user`,`outbound`,h(t))).slice(0,16),a=`${Math.floor((t+r)/1e3)}:${Rt(i)}`;return{username:a,credential:await e.relayPassword(`outbound`,a)}}function Bt(e){return`turn:${e.host.includes(`:`)?`[${e.host}]`:e.host}:${e.port}?transport=udp`}async function Vt(e,t,n,r){if(t.length===0)return[];let{username:i,credential:a}=await zt(e,n,r);return t.map(e=>({urls:Bt(e),username:i,credential:a}))}var B=class extends Error{deviceId;need;constructor(e,t,n){let r=t===`relay-only`?`only relayed connections are allowed`:`no direct path was found (${n?.cause instanceof Error?n.cause.message:String(n?.cause)})`;super(`a relay device is needed to reach device ${e}: ${r}, and no paired device advertises a relay and no TURN server is configured. Run the relay on an always-on device, or configure a TURN server.`,n?.cause===void 0?void 0:{cause:n.cause}),this.name=`MeshRelayNeededError`,this.deviceId=e,this.need=t}},Ht=class e{server;now;peers=[];owners;constructor(e,t){this.server=e,this.now=t}static async start(t={}){let n=t.now??Date.now,r,i=await Pt.start({...t.host===void 0?{}:{host:t.host},...t.port===void 0?{}:{port:t.port},...t.relayAddress===void 0?{}:{relayAddress:t.relayAddress},...t.relayPorts===void 0?{}:{relayPorts:t.relayPorts},...t.quotas===void 0?{}:{quotas:t.quotas},...t.allowPeer===void 0?{}:{allowPeer:t.allowPeer},...t.allowPrivatePeers===void 0?{}:{allowPrivatePeers:t.allowPrivatePeers},...t.onError===void 0?{}:{onError:t.onError},now:n,authorize:e=>r===void 0?Promise.resolve(void 0):r.authorize(e)});return r=new e(i,n),r}get endpoint(){let{address:e,port:t}=this.server.address;return{host:e,port:t}}allocationCount(e){return this.server.allocationCount(e)}declarePeers(e){this.peers=[...e],this.server.retain(new Set(e.map(e=>e.deviceId)))}async authorize(e){let t=Lt.exec(e);if(t===null)return;let n=this.now(),r=Number(t[1])*1e3;if(r<=n||r-n>366e4)return;let i=(await this.tagOwners(h(n))).get(t[2]);if(!(i===void 0||!this.peers.some(e=>e.deviceId===i.deviceId)))return{owner:i.deviceId,password:await i.rendezvous.relayPassword(`inbound`,e)}}tagOwners(e){let t=this.owners;if(t!==void 0&&t.epoch===e&&t.peers===this.peers)return t.byTag;let n=this.peers,r=(async()=>{let t=new Map;for(let r of n)for(let n of await r.rendezvous.lookupTags(`relay-user`,e))t.set(Rt(n.slice(0,16)),r);return t})();return r.catch(()=>{this.owners?.byTag===r&&(this.owners=void 0)}),this.owners={epoch:e,peers:n,byTag:r},r}close(){return this.peers=[],this.server.close()}};const Ut=2e4,Wt=1e3,Gt=3e3,Kt=`mesh-lists`,qt=`{"t":"${Kt}"`;function Jt(e){return{send:t=>e.send(t),onFrame:t=>e.onMessage(t),onClose:t=>e.readyState===`closed`?(queueMicrotask(t),()=>void 0):e.onStateChange(e=>{e===`closed`&&t()}),close:()=>e.close()}}var Yt=class{last;waiting;timer;run(e){let t=Date.now();if(this.last===void 0||t-this.last>=Wt){this.last=t,e();return}this.waiting=e,this.timer===void 0&&(this.timer=setTimeout(()=>{this.timer=void 0;let e=this.waiting;this.waiting=void 0,e!==void 0&&this.run(e)},Wt-(t-this.last)),this.timer.unref?.())}cancel(){this.timer!==void 0&&clearTimeout(this.timer),this.timer=void 0,this.waiting=void 0}};function Xt(){let e=new Uint8Array(16);return globalThis.crypto.getRandomValues(e),Buffer.from(e).toString(`base64url`)}function V(e,t){return t!==void 0&&t.seq>e.seq&&t.signingKeyId===e.signingKeyId}function H(e,t){return e===void 0?t:t===void 0?e:Math.max(e,t)}function Zt(e,t){let n=new Map;for(let r of[e.bySigningKey??{},t.bySigningKey??{}])for(let[e,t]of Object.entries(r)){let r=n.get(e)??{},i=H(r.rosterSeq,t.rosterSeq),a=H(r.revocationSeq,t.revocationSeq);n.set(e,{...i===void 0?{}:{rosterSeq:i},...a===void 0?{}:{revocationSeq:a}})}let r=Object.fromEntries(n),i=H(e.signingKeyRevocationSeq,t.signingKeyRevocationSeq);return{...i===void 0?{}:{signingKeyRevocationSeq:i},bySigningKey:r}}function Qt(e,t){let n=t.signingKeyCertificate.signingKeyId===e.signingKeyCertificate.signingKeyId;return{...t,...n&&V(t.roster,e.roster)?{roster:e.roster}:{},...n&&V(t.revocation,e.revocation)?{revocation:e.revocation}:{},...e.signingKeyRevocation.seq>t.signingKeyRevocation.seq?{signingKeyRevocation:e.signingKeyRevocation}:{},marks:Zt(e.marks,t.marks)}}function $t(e,t){return t.signingKeyCertificate.signingKeyId===e.signingKeyCertificate.signingKeyId?t.roster.seq>e.roster.seq||t.revocation.seq>e.revocation.seq||t.signingKeyRevocation.seq>e.signingKeyRevocation.seq:!1}function en(e){if(e.startsWith(qt))try{let t=JSON.parse(e);return typeof t==`object`&&t&&!Array.isArray(t)?t:void 0}catch{return{}}}var tn=class{options;instance=Xt();identity;sessionDescriptor;peers=new Map;byInbound=new Map;linkHandlers=new Set;refusalHandlers=new Set;waiters=new Set;unsubscribes=[];started=!1;stopped=!1;sync=Promise.resolve();constructor(e){this.options=e,this.identity=e.identity,this.sessionDescriptor=e.sessionDescriptor}get deviceId(){return this.identity.deviceCertificate.deviceId}async start(){if(this.started)throw Error(`DeviceMeshNode already started`);this.started=!0,this.unsubscribes.push(this.options.relay.onMessage((e,t)=>this.receive(e,t))),await this.syncPeers()}refresh(e){if(e.sessionDescriptor!==void 0&&(this.sessionDescriptor=e.sessionDescriptor),e.identity===void 0)return Promise.resolve();let t=this.identity;this.identity=Qt(t,e.identity);let n=this.syncPeers();return $t(t,this.identity)&&n.then(()=>this.pushLists(),()=>void 0),n}pushLists(){if(this.stopped)return;let{roster:e,revocation:t,signingKeyRevocation:n}=this.identity,r=JSON.stringify({t:Kt,roster:e,revocation:t,signingKeyRevocation:n});for(let e of this.peers.values())try{e.admitted?.exposed?.send(r)}catch{}}async receiveLists(e){let t=this.identity,n=s(this.options.cryptoContext,e.roster),r=o(this.options.cryptoContext,e.revocation),i=d(this.options.cryptoContext,e.signingKeyRevocation),a={...n.ok&&V(t.roster,n.value)?{roster:n.value}:{},...r.ok&&V(t.revocation,r.value)?{revocation:r.value}:{},...i.ok&&i.value.seq>t.signingKeyRevocation.seq?{signingKeyRevocation:i.value}:{}};if(Object.keys(a).length===0)return;let c=await ae(this.options.cryptoContext,{masterPublicKey:t.masterPublicKey,signingKeyCert:t.signingKeyCertificate,deviceCert:t.deviceCertificate,roster:a.roster??t.roster,revocation:a.revocation??t.revocation,signingKeyRevocation:a.signingKeyRevocation??t.signingKeyRevocation,now:(this.options.now??Date.now)(),lastSeen:t.marks,required:{roster:!0,revocation:!0,signingKeyRevocation:!0},listExpiryGraceMs:1/0});if(!c.ok||this.stopped)return;let{rosterSeq:l,revocationSeq:u,signingKeyRevocationSeq:f}=c.accepted;this.adoptLists({...a,marks:{...a.signingKeyRevocation!==void 0&&f!==void 0?{signingKeyRevocationSeq:f}:{},bySigningKey:{[c.signingKeyId]:{...a.roster!==void 0&&l!==void 0?{rosterSeq:l}:{},...a.revocation!==void 0&&u!==void 0?{revocationSeq:u}:{}}}}})}syncPeers(){this.sync=this.sync.then(async()=>{if(this.stopped)return;let e=this.identity,t=e.deviceCertificate,n=new Set(e.revocation.revokedDeviceIds),r=new Map;for(let i of e.roster.devices)i.deviceId!==t.deviceId&&!n.has(i.deviceId)&&r.set(i.deviceId,i);for(let[e,t]of this.peers){let n=r.get(e);(n===void 0||n.kaKey!==t.device.kaKey||n.kaEpoch!==t.device.kaEpoch)&&this.drop(t)}let i=[];for(let[n,a]of r){if(this.peers.has(n))continue;let r,o;try{r=await ee(this.options.cryptoContext,{ownKaPrivateKey:e.kaPrivateKey,own:t,peerDeviceId:n,lists:e}),o=await r.relayInbox()}catch{continue}let s={device:a,role:t.deviceId<a.deviceId?`offerer`:`answerer`,rendezvous:r,inbound:o.inbound,outbound:o.outbound,attempts:new Yt,replies:new Yt,relayFailures:0};this.peers.set(n,s),this.byInbound.set(o.inbound,s),i.push(s)}if(this.stopped)return;this.options.relayServer?.declarePeers([...this.peers.values()].map(e=>({deviceId:e.device.deviceId,rendezvous:e.rendezvous}))),this.options.relay.declarePresence([...this.byInbound.keys()]);let a=this.peerRoutes();this.options.relay.declarePeers?.(a),this.options.relays?.advertised?.(a,AbortSignal.timeout(Gt)).catch(()=>void 0);for(let e of i)this.hello(e)});let e=this.sync;return this.sync=e.catch(()=>void 0),e}drop(e){this.peers.delete(e.device.deviceId),this.byInbound.delete(e.inbound),e.attempts.cancel(),e.replies.cancel();let{pending:t,admitted:n}=e;if(e.pending=void 0,e.admitted=void 0,t?.link.close(),n?.link.close(),t!==void 0&&!this.stopped){let t={deviceId:e.device.deviceId,end:`closed`,error:Error(`peer device was revoked or is no longer in the roster`)};for(let e of this.refusalHandlers)e(t)}}roleFor(e){return this.peers.get(e)?.role}link(e){return this.peers.get(e)?.admitted?.exposed}connect(e,t=Ut){if(this.stopped)return Promise.reject(Error(`device mesh node stopped`));let n=this.peers.get(e);if(n===void 0)return Promise.reject(Error(`not a rostered, unrevoked peer device`));let r=n.admitted?.exposed;return r===void 0?new Promise((r,i)=>{let a=()=>{clearTimeout(s),c(),l(),this.waiters.delete(o)},o=e=>{a(),i(e)},s=setTimeout(()=>o(Error(`peer device did not connect in time`)),t);s.unref?.();let c=this.onLink(t=>{t.admission.deviceId===e&&(a(),r(t))}),l=this.onRefusal(t=>{t.deviceId===e&&o(t.error instanceof Error?t.error:Error(`connection ${t.end}`))});this.waiters.add(o),this.hello(n)}):Promise.resolve(r)}onLink(e){return this.linkHandlers.add(e),()=>this.linkHandlers.delete(e)}onRefusal(e){return this.refusalHandlers.add(e),()=>this.refusalHandlers.delete(e)}stop(){if(!this.stopped){this.stopped=!0;for(let e of this.unsubscribes.splice(0))e();for(let e of[...this.peers.values()])this.drop(e);for(let e of[...this.waiters])e(Error(`device mesh node stopped`));this.linkHandlers.clear(),this.refusalHandlers.clear()}}hello(e){this.stopped||this.options.relay.send(e.outbound,{v:1,kind:`hello`,from:this.instance})}receive(e,t){if(this.stopped)return;let n=this.byInbound.get(e);if(n===void 0)return;let r=et(t);if(r===void 0)return;if(r.kind===`hello`){this.onHello(n,r.from);return}if(r.to!==this.instance)return;if(r.kind===`offer`){this.onOffer(n,r);return}for(let e of[n.pending,n.admitted])if(e?.cid===r.cid&&e.remoteInstance===r.from){e.link.onSignal(U(r));return}let i=n.waitingOffer;r.kind===`ice`&&i?.cid===r.cid&&i.from===r.from&&i.ice.length<64&&i.ice.push(U(r))}serves(e,t){return e.admitted?.remoteInstance===t||e.pending?.remoteInstance===t}onHello(e,t){if(!this.serves(e,t)){if(e.role===`answerer`){e.replies.run(()=>this.hello(e));return}e.attempts.run(()=>{this.stopped||this.peers.get(e.device.deviceId)!==e||this.serves(e,t)||this.startAttempt(e,t,Xt()).link.offer()})}}onOffer(e,t){if(e.role!==`answerer`||e.admitted?.cid===t.cid||e.pending?.cid===t.cid)return;let n={cid:t.cid,from:t.from,ice:[]};e.waitingOffer=n,e.attempts.run(()=>{if(e.waitingOffer===n&&(e.waitingOffer=void 0),this.stopped||this.peers.get(e.device.deviceId)!==e||e.admitted?.cid===t.cid||e.pending?.cid===t.cid)return;let{link:r}=this.startAttempt(e,t.from,t.cid);r.onSignal(U(t));for(let e of n.ice)r.onSignal(e)})}startAttempt(e,t,n){let r=e.pending;e.pending=void 0,r?.link.close();let i=r=>{this.stopped||this.options.relay.send(e.outbound,{v:1,from:this.instance,to:t,cid:n,...r})},a,o=new at({role:e.role,createPeer:async()=>{let{stage:t,servers:n}=await this.relayStage(e);return a!==void 0&&(a.relayStage=t),this.createPeer(n)},sendSignal:i,startHandshake:t=>ne(this.options.cryptoContext,{role:e.role===`offerer`?`initiator`:`responder`,identity:this.identity,sessionDescriptor:this.sessionDescriptor,...e.role===`offerer`?{expectedPeerDeviceId:e.device.deviceId}:{},localFingerprint:t.localFingerprint,remoteFingerprint:t.remoteFingerprint,locality:`another-host`,localPolicy:this.options.localPolicy,send:t.send,...this.options.fetchLatestLists===void 0?{}:{fetchLatestLists:this.options.fetchLatestLists},onListsAdopted:e=>this.adoptLists(e),...this.options.now===void 0?{}:{now:this.options.now},...this.options.handshakeTimeoutMs===void 0?{}:{timeoutMs:this.options.handshakeTimeoutMs}}),connectTimeoutMs:this.options.connectTimeoutMs??Ut,accepts:t=>t.admission.deviceId===e.device.deviceId,onAdmitted:t=>this.admitted(e,o,t),onEnded:(t,n)=>this.ended(e,o,t,n)});return a={cid:n,remoteInstance:t,link:o},e.pending=a,a}adoptLists(e){let t=this.identity,n={...t,...V(t.roster,e.roster)?{roster:e.roster}:{},...V(t.revocation,e.revocation)?{revocation:e.revocation}:{},...e.signingKeyRevocation!==void 0&&e.signingKeyRevocation.seq>t.signingKeyRevocation.seq?{signingKeyRevocation:e.signingKeyRevocation}:{},marks:Zt(t.marks,e.marks)};this.refresh({identity:n}).catch(()=>void 0),this.options.onListsAdopted?.(e)}admitted(e,t,n){let r=e.pending;if(r===void 0||r.link!==t)return;if(n.admission.deviceId!==e.device.deviceId){t.close();return}let i=n.admission,a=t.channelBinding;if(a===void 0){t.close();return}let o=new se({deviceId:i.deviceId,sessionId:i.sessionId,locality:i.locality,capabilities:i.capabilities},this.options.operatorApprover);t.onEnd(()=>o.close());let s=o.authorize(`message`);t.onMessage(e=>{let t=en(e);t!==void 0&&this.receiveLists(t).catch(()=>void 0)});let c={admission:i,result:n,channelBinding:a,authority:o,send:e=>t.send(e),onMessage:e=>t.onMessage(n=>{en(n)===void 0&&s.then(r=>{r.allowed&&!t.ended?e(n):t.close()})}),openFileChannel:async()=>Jt(await t.openFileChannel()),onFileChannel:e=>t.onFileChannel(t=>e(Jt(t))),onClose:e=>t.onEnd(()=>e()),close:()=>t.close()};r.exposed=c,e.relayFailures=0;let l=e.admitted;e.admitted=r,e.pending=void 0,l?.link.close(),this.options.relay.confirmPeer?.(i.deviceId);for(let e of this.linkHandlers)e(c)}ended(e,t,n,r){if(e.admitted?.link===t){e.admitted=void 0;return}if(e.pending?.link!==t)return;let i=e.pending.relayStage;e.pending=void 0;let a=r.stage===`connecting`&&(n===`timeout`||r.peer?.state===`failed`)&&r.peer?.history.includes(`connected`)!==!0,o=r;r.cause instanceof B?o=r.cause:a&&i===`direct`?o=new B(e.device.deviceId,`no-direct-path`,{cause:r}):a&&(e.relayFailures+=1);let s={deviceId:e.device.deviceId,end:n,error:o};for(let e of this.refusalHandlers)e(s)}async relayStage(e){let t=this.options.relays,n=[],r=await this.embeddedRelays(e);if(r.length>0&&n.push({stage:`embedded`,servers:r}),t?.configured!==void 0&&t.configured.length>0&&n.push({stage:`configured`,servers:t.configured}),n.length===0){if(t?.relayOnly===!0)throw new B(e.device.deviceId,`relay-only`);return{stage:`direct`,servers:[]}}return n[e.relayFailures%n.length]}peerRoutes(e){let t=[...this.peers.values()];return(e===void 0?t:[e,...t.filter(t=>t!==e)]).map(e=>({deviceId:e.device.deviceId,inbound:e.inbound,outbound:e.outbound,rendezvous:e.rendezvous}))}async embeddedRelays(e){let t=this.options.relays?.advertised;if(t===void 0)return[];let n;try{n=await t(this.peerRoutes(e),AbortSignal.timeout(Gt))}catch{return[]}let r=e.device.deviceId,i=[r,...[...n.keys()].filter(e=>e!==r)],a=(this.options.now??Date.now)(),o=[],s=0;for(let e of i){if(s>=2)break;let t=n.get(e),r=this.peers.get(e);t!==void 0&&t.length!==0&&r!==void 0&&(s+=1,o.push(...await Vt(r.rendezvous,t.slice(0,3),a,this.options.relays?.credentialTtlMs)))}return o}createPeer(e){let t=[...this.options.iceServers??[],...e];return new T({...t.length>0?{iceServers:t}:{},...this.options.relays?.relayOnly===!0?{forceTurn:!0}:{},...this.options.loadDataChannel===void 0?{}:{loadDataChannel:this.options.loadDataChannel}})}};function U(e){return e.kind===`ice`?{kind:`ice`,candidate:{...e.candidate}}:{kind:e.kind,sdp:e.sdp}}function nn(){let e=new Map;return{connect(){let t={messages:new Set,absents:new Set,topics:new Set,open:!0},n=()=>{for(let n of t.topics)e.get(n)===t&&e.delete(n);t.topics=new Set};return{declarePresence(r){if(t.open){n(),t.topics=new Set(r);for(let n of r)e.set(n,t)}},send(n,r){if(!t.open)return;let i=JSON.parse(JSON.stringify(r));queueMicrotask(()=>{let r=e.get(n);if(r===void 0||r===t||!r.open){for(let e of t.absents)e(n);return}for(let e of r.messages)e(n,i)})},onMessage(e){return t.messages.add(e),()=>t.messages.delete(e)},onAbsent(e){return t.absents.add(e),()=>t.absents.delete(e)},close(){t.open=!1,n(),t.messages.clear(),t.absents.clear()}}}}}var rn=class{options;socket;messages=new Set;absents=new Set;outbox=[];topics;closed=!1;constructor(e){this.options=e;let t=e.createSocket??(e=>new g(e));this.socket=t(e.url),this.socket.on(`open`,()=>this.flush()),this.socket.on(`message`,e=>this.receive(e)),this.socket.on(`error`,e=>this.options.onError?.(e instanceof Error?e:Error(String(e)))),this.socket.on(`close`,()=>{this.closed||this.options.onError?.(Error(`signaling relay connection closed`))})}flush(){this.topics!==void 0&&this.write({type:`presence`,topics:this.topics});for(let e of this.outbox.splice(0))this.socket.send(e)}write(e){this.socket.send(JSON.stringify(e))}receive(e){let t;try{t=JSON.parse(typeof e==`string`?e:String(e))}catch{return}if(typeof t!=`object`||!t)return;let n=t;if(n.type===`message`&&typeof n.topic==`string`)for(let e of this.messages)e(n.topic,n.data);else if(n.type===`absent`&&typeof n.topic==`string`)for(let e of this.absents)e(n.topic);else n.type===`present`?this.options.onPresent?.():n.type===`error`&&this.options.onError?.(Error(`signaling relay refused a frame: ${String(n.reason)}`))}declarePresence(e){this.closed||(this.topics=[...e],this.socket.readyState===1&&this.write({type:`presence`,topics:this.topics}))}send(e,t){if(this.closed)return;let n=JSON.stringify({type:`message`,topic:e,data:t});this.socket.readyState===1?this.socket.send(n):this.outbox.length<256?this.outbox.push(n):this.options.onError?.(Error(`signaling relay is not reachable; message dropped`))}onMessage(e){return this.messages.add(e),()=>this.messages.delete(e)}onAbsent(e){return this.absents.add(e),()=>this.absents.delete(e)}close(){this.closed=!0,this.messages.clear(),this.absents.clear(),this.outbox.length=0,this.socket.close()}};const an=3;function on(e){return{candidates:t=>Promise.resolve(e.recall(t.deviceId))}}function sn(e,t){return e.host===t.host&&e.port===t.port}function cn(e,t){return[{host:t.host,port:t.port},...e.filter(e=>!sn(e,t))].slice(0,3)}function ln(){let e=new Map,t;return{recall:t=>e.get(t)??[],remember:(t,n)=>{e.set(t,cn(e.get(t)??[],n))},retain:t=>{let n=new Set(t);for(let t of[...e.keys()])n.has(t)||e.delete(t)},lastListenPort:()=>t,rememberListenPort:e=>{t=e}}}const un=/^[A-Za-z0-9_-]{43}$/,dn=/^[A-Za-z0-9_-]{22}$/,fn=12e4,pn=1008;function W(e){return _(`sha256`).update(`lan-address:${e}`).digest(`base64url`)}function mn(e,t){return v(`sha256`,e).update(`lan-present:${t}`).digest(`base64url`)}function hn(e,t,n){if(typeof n!=`string`)return!1;let r=Buffer.from(mn(e,t)),i=Buffer.from(n);return i.length===r.length&&y(i,r)}function gn(e,t){return new Promise((n,r)=>{let i=new oe({port:e,...t===void 0?{}:{host:t},maxPayload:65536,perMessageDeflate:!1,verifyClient:e=>e.origin===void 0||e.origin===``}),a=e=>{i.close(),r(e)};i.once(`error`,a),i.once(`listening`,()=>{i.off(`error`,a),n(i)})})}function _n(e){let t;try{t=JSON.parse(String(e))}catch{return}if(typeof t!=`object`||!t||Array.isArray(t))return;let n=t;if(!(typeof n.type!=`string`||typeof n.to!=`string`||!un.test(n.to)))return n.type===`probe`?typeof n.nonce==`string`&&dn.test(n.nonce)?{type:n.type,to:n.to,nonce:n.nonce}:void 0:{type:n.type,to:n.to,data:n.data}}async function vn(e={}){let t;try{t=await gn(e.port??0,e.host)}catch(n){if(e.port===void 0||e.port===0)throw n;t=await gn(0,e.host)}let n=t.address(),r=typeof n==`object`&&n?n.port:0,i=new Map,a=new Set;return t.on(`connection`,e=>{if(t.clients.size>32){e.close(pn);return}let n=0,r=Date.now(),o=setTimeout(()=>e.close(),fn);o.unref?.(),e.on(`close`,()=>clearTimeout(o)),e.on(`error`,()=>e.close()),e.on(`message`,t=>{let s=Date.now();if(s-r>1e4&&(r=s,n=0),n+=1,n>128){e.close(pn);return}clearTimeout(o),o=setTimeout(()=>e.close(),fn),o.unref?.();let c=_n(t);if(c===void 0)return;let l=i.get(c.to);if(l===void 0){e.send(JSON.stringify({type:`absent`,to:c.to}));return}if(c.type===`probe`&&c.nonce!==void 0){e.send(JSON.stringify({type:`present`,to:c.to,nonce:c.nonce,proof:mn(l,c.nonce)}));return}if(c.type===`message`)for(let e of a)e(l,c.data)})}),{port:r,setPresence(e){i=new Map(e.map(e=>[W(e),e]))},onMessage(e){return a.add(e),()=>a.delete(e)},close(){a.clear(),i=new Map;for(let e of t.clients)e.terminate();return new Promise(e=>t.close(()=>e()))}}}const G=`_rdv._tcp.local`;function yn(){return e(import.meta.url)(`multicast-dns`)()}function bn(){let e=[];for(let t of Object.values(x()))for(let n of t??[])n.internal||(n.family===`IPv4`||n.family===`IPv6`&&!n.address.startsWith(`fe80`))&&e.push(n.address);return e}function xn(e){let t=new Uint8Array(e);return globalThis.crypto.getRandomValues(t),Buffer.from(t).toString(`hex`)}function Sn(e){return Buffer.from(e.subarray(0,16)).toString(`hex`)}function Cn(e){return Math.max(8,Math.ceil(e/8)*8)}function K(e,t){return e.toLowerCase()===t.toLowerCase()}var wn=class{options;transport;routes=[];port;records;instances=new Set;timer;generation=0;closed=!1;epochCover;announced;lastAnswer;answerTimer;constructor(e={}){this.options=e}now(){return(this.options.now??Date.now)()}open(){if(!this.closed){if(this.transport!==void 0)return this.transport;try{let e=(this.options.createTransport??yn)();return e.on(`query`,e=>this.onQuery(e)),e.on(`error`,e=>this.options.onError?.(e)),this.transport=e,e}catch(e){this.closed=!0,this.options.onError?.(e instanceof Error?e:Error(String(e)));return}}}advertise(e,t){return this.routes=e,this.port=t,this.rebuild()}async rebuild(){let e=++this.generation,t=this.port;if(this.closed||t===void 0)return;let n=h(this.now()),r=await Promise.all(this.routes.map(e=>e.rendezvous.tag(`mdns`,`outbound`,n)));if(e!==this.generation||this.closed)return;this.epochCover?.epoch!==n&&(this.epochCover={epoch:n,padding:[],target:`${xn(8)}.local`});let{padding:i,target:a}=this.epochCover,o=Cn(r.length)-r.length;for(;i.length<o;)i.push(xn(16));let s=[...r.map(Sn),...i.slice(0,o)].sort(),c=JSON.stringify([n,t,s]),l=s.map(e=>({name:G,type:`PTR`,ttl:120,data:`${e}.${G}`})),u=[];for(let e of s){let n=`${e}.${G}`;u.push({name:n,type:`SRV`,ttl:120,data:{priority:0,weight:0,port:t,target:a}},{name:n,type:`TXT`,ttl:120,data:[]})}for(let e of(this.options.addresses??bn)())u.push({name:a,type:e.includes(`:`)?`AAAA`:`A`,ttl:120,data:e});this.records={answers:l,additionals:u},this.instances=new Set(s.map(e=>`${e}.${G}`.toLowerCase())),this.schedule(n),c!==this.announced&&(this.announced=c,this.open()?.respond(this.records))}schedule(e){this.timer!==void 0&&clearTimeout(this.timer);let t=Math.max(0,(e+1)*a-this.now());this.timer=setTimeout(()=>{this.rebuild().catch(()=>void 0)},t),this.timer.unref?.()}onQuery(e){this.records===void 0||this.closed||(e.questions??[]).some(e=>K(e.name,`_rdv._tcp.local`)&&(e.type===`PTR`||e.type===`ANY`)||this.instances.has(e.name.toLowerCase()))&&this.answer()}answer(){if(this.answerTimer!==void 0)return;let e=this.options.minAnswerIntervalMs??500,t=this.lastAnswer===void 0?0:this.lastAnswer+e-this.now(),n=()=>{this.answerTimer=void 0,!(this.closed||this.records===void 0)&&(this.lastAnswer=this.now(),this.transport?.respond(this.records))};if(t<=0){n();return}this.answerTimer=setTimeout(n,t),this.answerTimer.unref?.()}async candidates(e,t){let n=this.open();if(n===void 0||t.aborted)return[];let r=h(this.now()),i=new Set((await e.rendezvous.lookupTags(`mdns`,r)).map(e=>`${Sn(e)}.${G}`));return t.aborted||this.closed?[]:new Promise(e=>{let r=[],a,o=()=>{clearTimeout(c),clearTimeout(a),t.removeEventListener(`abort`,o),n.removeListener(`response`,s),e(r)},s=(e,t)=>{let n=[...e.answers??[],...e.additionals??[]];for(let e of n){if(e.type!==`PTR`||!K(e.name,`_rdv._tcp.local`)||typeof e.data!=`string`||!i.has(e.data.toLowerCase()))continue;let a=n.find(t=>t.type===`SRV`&&K(t.name,e.data))?.data?.port;if(typeof a!=`number`||!Number.isInteger(a)||a<=0||a>65535)continue;let o=r.filter(e=>e.host===t.address);r.length<8&&o.length<2&&!o.some(e=>e.port===a)&&r.push({host:t.address,port:a})}r.length!==0&&a===void 0&&(a=setTimeout(o,this.options.answerGraceMs??200),a.unref?.())},c=setTimeout(o,this.options.lookupTimeoutMs??1e3);c.unref?.(),t.addEventListener(`abort`,o,{once:!0}),n.on(`response`,s),n.query({questions:[{name:G,type:`PTR`}]})})}close(){this.closed=!0,this.generation+=1,this.timer!==void 0&&clearTimeout(this.timer),this.answerTimer!==void 0&&clearTimeout(this.answerTimer),this.transport?.destroy(),this.transport=void 0}};function Tn(){let e=new Set,t=[],n=(t,n,r)=>{let i=JSON.parse(JSON.stringify(n));queueMicrotask(()=>{for(let n of e)for(let e of r(n))e(i,{address:t.address})})};return{responses:t,transport(r){let i={address:r,queries:new Set,responses:new Set};return e.add(i),{on(e,t){e===`query`&&i.queries.add(t),e===`response`&&i.responses.add(t)},removeListener(e,t){i.responses.delete(t)},query(e){n(i,e,e=>e.queries)},respond(e){t.push(JSON.parse(JSON.stringify(e))),n(i,e,e=>e.responses)},destroy(){e.delete(i)}}}}}var En=class{until=new Map;failures=new Map;has(e,t){let n=this.until.get(e);return n===void 0?!1:n>t?!0:(this.until.delete(e),!1)}fail(e,t,n){let r=(this.failures.get(e)??0)+1;this.failures.delete(e),this.failures.set(e,r);for(let e of this.failures.keys()){if(this.failures.size<=32)break;this.failures.delete(e),this.until.delete(e)}let i=Math.min(2**(r-1),16);this.until.set(e,t+n*i)}clear(){this.until.clear(),this.failures.clear()}};function Dn(e){if(typeof e!=`object`||!e)return!1;let t=e.kind;return t===`hello`||t===`offer`||t===`answer`}function On(e){return`${e.host}:${e.port}`}function kn(){let e=new Uint8Array(16);return globalThis.crypto.getRandomValues(e),Buffer.from(e).toString(`base64url`)}function An(e){return Buffer.from(e).toString(`base64url`)}function jn(e){return`ws://${e.host.includes(`:`)?`[${e.host}]`:e.host}:${e.port}`}function Mn(e){try{let t=JSON.parse(String(e));return typeof t==`object`&&t?t:void 0}catch{return}}var Nn=class{options;routes=new Map;byDevice=new Map;lanIn=new Map;messages=new Set;absents=new Set;unsubscribes=[];abort=new AbortController;sync=Promise.resolve();pendingPeers=0;waiting=[];timer;closed=!1;constructor(e){this.options=e;for(let e of this.carriers())this.unsubscribes.push(e.onMessage((e,t)=>this.deliver(e,t)),e.onAbsent(e=>this.absent(e)));this.unsubscribes.push(e.listener.onMessage((e,t)=>{let n=this.lanIn.get(e);n!==void 0&&this.deliver(n,t)}))}now(){return(this.options.now??Date.now)()}carriers(){return[...this.options.signaling??[],...this.options.relay===void 0?[]:[this.options.relay]]}deliver(e,t){if(!this.closed)for(let n of this.messages)n(e,t)}absent(e){if(!this.closed)for(let t of this.absents)t(e)}declarePresence(e){for(let t of this.carriers())t.declarePresence(e)}declarePeers(e){for(let t of this.carriers())t.declarePeers?.(e);this.pendingPeers+=1,this.sync=this.sync.then(()=>this.applyPeers(e)).catch(e=>{this.options.onError?.(e instanceof Error?e:Error(String(e)))}).finally(()=>{if(--this.pendingPeers,!(this.pendingPeers>0))for(let{topic:e,data:t}of this.waiting.splice(0))this.send(e,t)})}async applyPeers(e){if(this.closed)return;let t=h(this.now()),n=new Map,r=new Map;for(let i of e){let e=An(await i.rendezvous.tag(`lan-inbox`,`outbound`,t));for(let e of await i.rendezvous.lookupTags(`lan-inbox`,t))n.set(An(e),i.inbound);let a=this.routes.get(i.outbound),o=a!==void 0&&a.route.deviceId===i.deviceId?a:{route:i,lanOut:e,path:{kind:`unresolved`},avoid:new En,avoidCarriers:new En};o.route=i,o.lanOut=e,r.set(i.outbound,o)}if(!this.closed){for(let[e,t]of this.routes)r.get(e)!==t&&this.reset(t);this.routes.clear(),this.byDevice.clear();for(let[e,t]of r)this.routes.set(e,t),this.byDevice.set(t.route.deviceId,t);this.lanIn=n,this.options.listener.setPresence([...n.keys()]),this.cacheWrite(()=>this.options.cache?.retain(e.map(e=>e.deviceId))),await Promise.all((this.options.advertisers??[]).map(t=>t.advertise(e,this.options.listener.port))),!this.closed&&this.scheduleEpoch(t,e)}}scheduleEpoch(e,t){this.timer!==void 0&&clearTimeout(this.timer);let n=Math.max(0,(e+1)*a-this.now());this.timer=setTimeout(()=>this.declarePeers(t),n),this.timer.unref?.()}confirmPeer(e){let t=this.byDevice.get(e),n=t?.path;if(!(t===void 0||n?.kind!==`direct`&&n?.kind!==`relay`)){if(clearTimeout(n.deadline),n.deadline=void 0,n.kind===`relay`){t.avoidCarriers.clear();return}t.avoid.clear(),this.cacheWrite(()=>this.options.cache?.remember(e,n.candidate))}}cacheWrite(e){try{e()}catch(e){this.options.onError?.(e instanceof Error?e:Error(String(e)))}}send(e,t){if(this.closed)return;if(this.pendingPeers>0){this.waiting.length<256?this.waiting.push({topic:e,data:t}):this.viaRelay(e,t);return}let n=this.routes.get(e);if(n===void 0){this.viaRelay(e,t);return}let r=n.path;if(r.kind===`direct`&&r.socket.readyState===1){this.sendDirect(n,r,t);return}if(r.kind===`relay`&&this.now()<r.until){this.viaCarrier(n,r,t);return}if(r.kind===`resolving`){r.queue.length<256?r.queue.push(t):this.viaRelay(e,t);return}r.kind===`direct`&&this.reset(n);let i=[t];n.path={kind:`resolving`,queue:i},this.resolve(n,i)}sendDirect(e,t,n){Dn(n)&&this.armDeadline(e,t),t.socket.send(JSON.stringify({type:`message`,to:W(e.lanOut),data:n}))}viaRelay(e,t){let n=this.carriers().at(-1);if(n===void 0){queueMicrotask(()=>this.absent(e));return}n.send(e,t)}viaCarrier(e,t,n){Dn(n)&&t.carrier!==this.carriers().at(-1)&&this.armDeadline(e,t),t.carrier.send(e.route.outbound,n)}async resolve(e,t){let n=new Set;for(let r of this.options.sources){if(this.closed||e.path.kind!==`resolving`)return;for(let i of await this.look(r,e.route)){let r=On(i);if(n.size>=8)break;if(n.has(r)||e.avoid.has(r,this.now()))continue;n.add(r);let a=await this.probe(i,e.lanOut);if(a===void 0)continue;if(this.closed||e.path.kind!==`resolving`||this.routes.get(e.route.outbound)!==e){a.close();return}let o=this.useDirect(e,a,i);for(let n of t)this.sendDirect(e,o,n);return}}if(this.closed||e.path.kind!==`resolving`)return;this.fallBack(e);let r=e.path;for(let n of t)r.kind===`relay`?this.viaCarrier(e,r,n):this.viaRelay(e.route.outbound,n)}fallBack(e){let t=this.now(),n=this.carriers(),r=n.find(n=>!e.avoidCarriers.has(n,t))??n.at(-1);e.path=r===void 0?{kind:`unresolved`}:{kind:`relay`,until:t+this.recheckMs(),carrier:r}}recheckMs(){return this.options.relayRecheckMs??3e4}async look(e,t){let n=AbortSignal.timeout(e.timeoutMs??this.options.sourceTimeoutMs??1500),r=AbortSignal.any([n,this.abort.signal]);try{return await Promise.race([e.candidates(t,r),new Promise(e=>r.addEventListener(`abort`,()=>e([]),{once:!0}))])}catch{return[]}}probe(e,t){let n=W(t),r=kn();return new Promise(i=>{let a;try{a=(this.options.connect??(e=>new g(jn(e),{maxPayload:4096})))(e)}catch{i(void 0);return}let o=!1,s=e=>{o||(o=!0,clearTimeout(c),e||a.close(),i(e?a:void 0))},c=setTimeout(()=>s(!1),this.options.probeTimeoutMs??1500);c.unref?.(),a.on(`open`,()=>a.send(JSON.stringify({type:`probe`,to:n,nonce:r}))),a.on(`message`,e=>{let i=Mn(e);if(i?.to===n){if(i.type===`absent`){s(!1);return}s(hn(t,r,i.proof))}}),a.on(`error`,()=>s(!1)),a.on(`close`,()=>s(!1))})}armDeadline(e,t){t.deadline===void 0&&(t.deadline=setTimeout(()=>{e.path===t&&(t.kind===`direct`?e.avoid.fail(On(t.candidate),this.now(),this.recheckMs()):e.avoidCarriers.fail(t.carrier,this.now(),this.recheckMs()),this.reset(e),this.fallBack(e))},this.options.admissionTimeoutMs??2e4),t.deadline.unref?.())}useDirect(e,t,n){let r={kind:`direct`,socket:t,candidate:n};e.path=r;let i=()=>{e.path===r&&this.reset(e)};return t.on(`close`,i),t.on(`error`,i),t.on(`message`,t=>{let n=Mn(t);n?.type===`absent`&&n.to===W(e.lanOut)&&i()}),r}reset(e){let t=e.path;e.path={kind:`unresolved`},t.kind===`relay`&&clearTimeout(t.deadline),t.kind===`direct`&&(clearTimeout(t.deadline),t.socket.close())}onMessage(e){return this.messages.add(e),()=>this.messages.delete(e)}onAbsent(e){return this.absents.add(e),()=>this.absents.delete(e)}close(){if(!this.closed){this.closed=!0,this.abort.abort(),this.timer!==void 0&&clearTimeout(this.timer);for(let e of this.unsubscribes.splice(0))e();for(let e of this.routes.values())this.reset(e);this.routes.clear(),this.byDevice.clear(),this.messages.clear(),this.absents.clear(),this.waiting=[];for(let e of this.options.advertisers??[])e.close();this.options.listener.close().catch(()=>void 0)}}};async function Pn(e={}){let t=e.cache??ln(),n=t.lastListenPort(),r=await vn({...n===void 0?{}:{port:n},...e.host===void 0?{}:{host:e.host}});try{t.rememberListenPort(r.port)}catch(t){e.onError?.(t instanceof Error?t:Error(String(t)))}let i=e.mdns===!1?void 0:new wn({...e.onError===void 0?{}:{onError:e.onError},...e.mdns}),a=e.internet?.dht,o=e.internet?.signaling??[];return new Nn({...e.relay===void 0?{}:{relay:e.relay},...o.length>0?{signaling:o}:{},listener:r,sources:[on(t),...i===void 0?[]:[i],...a===void 0?[]:[a]],cache:t,advertisers:[...i===void 0?[]:[i],...a===void 0?[]:[a]],...e.onError===void 0?{}:{onError:e.onError}})}const Fn=Uint8Array.from([48,46,2,1,0,48,5,6,3,43,101,112,4,34,4,32]),q=new TextEncoder,In=new TextDecoder;function J(e){return e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength)}function Ln(e){let t=atob(e.replace(/-/g,`+`).replace(/_/g,`/`)),n=new Uint8Array(t.length);for(let e=0;e<t.length;e+=1)n[e]=t.charCodeAt(e);return n}function Y(e){let t=new Uint8Array(e.reduce((e,t)=>e+t.length,0)),n=0;for(let r of e)t.set(r,n),n+=r.length;return t}function Rn(e,t){if(e.length!==t.length)return!1;let n=0;for(let r=0;r<e.length;r+=1)n|=e[r]^t[r];return n===0}async function zn(e){if(e.length!==32)throw Error(`an Ed25519 seed is 32 bytes`);let t=await globalThis.crypto.subtle.importKey(`pkcs8`,J(Y([Fn,e])),{name:`Ed25519`},!0,[`sign`]),n=await globalThis.crypto.subtle.exportKey(`jwk`,t);if(typeof n.x!=`string`)throw Error(`Ed25519 public key unavailable`);return{publicKey:Ln(n.x),sign:async e=>new Uint8Array(await globalThis.crypto.subtle.sign({name:`Ed25519`},t,J(e)))}}async function Bn(e,t,n){if(e.length!==32||n.length!==64)return!1;try{let r=await globalThis.crypto.subtle.importKey(`raw`,J(e),{name:`Ed25519`},!1,[`verify`]);return await globalThis.crypto.subtle.verify({name:`Ed25519`},r,J(n),J(t))}catch{return!1}}function X(e,t,n){let r=[];return e!==void 0&&e.length>0&&r.push(q.encode(`4:salt${e.length}:`),e),r.push(q.encode(`3:seqi${t}e1:v${n.length}:`),n),Y(r)}async function Vn(e,t,n,r){if(r.length>999)throw Error(`record value exceeds 999 bytes`);if(t!==void 0&&t.length>64)throw Error(`salt exceeds 64 bytes`);if(!Number.isSafeInteger(n)||n<0)throw Error(`seq must be a non-negative integer`);let i=await e.sign(X(t,n,r));return{k:e.publicKey,...t===void 0?{}:{salt:t},seq:n,v:r,sig:i}}async function Z(e,t,n){return!Rn(e.k,t)||!Rn(e.salt??new Uint8Array,n??new Uint8Array)||e.v.length>999||!Number.isSafeInteger(e.seq)||e.seq<0?!1:Bn(t,X(n,e.seq,e.v),e.sig)}const Hn={hints:`bep44-salt`,revocation:`bep44-revocation-salt`};async function Un(e){return new Uint8Array(await globalThis.crypto.subtle.digest(`SHA-256`,J(Y(e))))}async function Wn(e,t,n,r,i=0){let[a,o]=await Promise.all([e.signingSeed(n,r,t),e.tag(Hn[t],n,r)]);if(i===0)return{key:await zn(a),salt:o};let s=q.encode(`chunk`),c=Uint8Array.of(i),[l,u]=await Promise.all([Un([s,a,c]),Un([s,o,c])]);return{key:await zn(l),salt:u}}async function Gn(e){let t=q.encode(JSON.stringify(e)),n=(await Un([t])).subarray(0,8),r=Math.max(1,Math.ceil(t.length/854));if(r>8)throw Error(`device lists too large to publish as records`);return Array.from({length:r},(e,i)=>{let a=new Uint8Array(864).fill(32);return a[0]=r,a[1]=i,a.set(n,2),a.set(t.subarray(i*854,(i+1)*854),10),a})}function Kn(e){let t=e[0];if(e.length===864&&e[1]===0)return t!==void 0&&t>=1&&t<=8?t:void 0}function qn(e){let t=e.length,n=e[0]?.subarray(2,10),r=[];for(let[i,a]of e.entries()){if(a.length!==864||a[0]!==t||a[1]!==i||!Jn(a.subarray(2,10),n))return;r.push(a.subarray(10))}return Xn(Y(r))}function Jn(e,t){return t!==void 0&&e.length===t.length&&e.every((e,n)=>e===t[n])}function Yn(e,t){let n=q.encode(JSON.stringify(e));if(n.length>t)throw Error(`record does not fit its fixed size`);let r=new Uint8Array(t).fill(32);return r.set(n),r}function Xn(e){try{return JSON.parse(In.decode(e))}catch{return}}function Zn(e,t){let n=[];for(let r of e){if(n.length>=t)break;r.host.length===0||r.host.length>64||n.push([r.host,r.port])}return n}function Qn(e,t=[]){let n=Zn(e,8),r=Zn(t,4);for(;;)try{return Yn({v:1,c:n,...r.length>0?{t:r}:{}},640)}catch(e){if(n.length>0)n.pop();else if(r.length>0)r.pop();else throw e}}const $n=/^[0-9A-Za-z.:%_-]{1,64}$/;function er(e){return nr(e,`c`,8)}function tr(e){return nr(e,`t`,4)}function nr(e,t,n){let r=Xn(e);if(typeof r!=`object`||!r)return[];let i=r,a=i[t];if(i.v!==1||!Array.isArray(a))return[];let o=[];for(let e of a.slice(0,n)){if(!Array.isArray(e)||e.length!==2)continue;let[t,n]=e;typeof t!=`string`||!$n.test(t)||typeof n!=`number`||!Number.isInteger(n)||n<1||n>65535||o.push({host:t,port:n})}return o}function rr(e,t=Math.random){let n=t();return Math.floor((Number.isFinite(n)?Math.min(Math.max(n,0),1):0)*Math.max(0,e))}const ir=9e4;function ar(e){if(typeof e!=`object`||!e)return-1;let t=e.seq;return typeof t==`number`&&Number.isSafeInteger(t)?t:-1}function or(e){return e instanceof Error?e:Error(String(e))}var sr=class{options;timeoutMs;scheduled=new Map;routes=[];listsFound;prefetchedEpoch;relaysFound=new Map;relayLookups=new Map;closed=!1;constructor(e){this.options=e,this.timeoutMs=e.lookupTimeoutMs??6e3}now(){return(this.options.now??Date.now)()}async candidates(e,t){let n=h(this.now()),r=await this.lookup(e,`hints`,n,t);t.aborted||this.rememberRelays(e,n,r);let i=[],a=new Set;for(let e of r.sort((e,t)=>t.epoch-e.epoch))for(let t of er(e.data)){let e=`${t.host}:${t.port}`;a.has(e)||(a.add(e),i.push(t))}return i}rememberRelays(e,t,n){let r=[...n].sort((e,t)=>t.epoch-e.epoch)[0],i=r===void 0?[]:tr(r.data);this.relaysFound.set(e.deviceId,{epoch:t,checkedAt:this.now(),endpoints:i})}async relayAdverts(e,t){let n=this.now(),r=h(n),i=e.slice(0,16),a=[];for(let e of i){let t=this.relaysFound.get(e.deviceId);t!==void 0&&t.epoch===r&&(t.endpoints.length>0||n-t.checkedAt<12e4)||a.push(this.lookUpRelay(e,r))}if(a.length>0){let e=new Promise(e=>{t.aborted&&e(),t.addEventListener(`abort`,()=>e(),{once:!0})});await Promise.race([Promise.all(a),e])}let o=new Set(e.map(e=>e.deviceId));for(let e of[...this.relaysFound.keys()])o.has(e)||this.relaysFound.delete(e);let s=new Map;for(let e of i){let t=this.relaysFound.get(e.deviceId)?.endpoints??[];t.length>0&&s.set(e.deviceId,t)}return s}lookUpRelay(e,t){let n=this.relayLookups.get(e.deviceId);if(n!==void 0)return n;let r=AbortSignal.timeout(this.timeoutMs),i=this.lookup(e,`hints`,t,r).then(n=>{!r.aborted&&!this.closed&&this.rememberRelays(e,t,n)}).finally(()=>this.relayLookups.delete(e.deviceId));return this.relayLookups.set(e.deviceId,i),i}async lookup(e,t,n,r){let i=[n-1,n,n+1].flatMap(n=>this.options.stores.map(async i=>{let a=await this.read(i,e,t,n,0,r);return a===void 0?void 0:{epoch:n,data:a}}));return(await Promise.all(i)).filter(e=>e!==void 0)}async read(e,t,n,r,i,a){try{let o=await Wn(t.rendezvous,n,`inbound`,r,i),s=await e.get(o.key.publicKey,o.salt,a);if(s===void 0)return;let c=await t.rendezvous.openRecord(s,r,n);return c?.epoch===r?c.hints:void 0}catch{return}}async lookupLists(e,t,n){let r=[t-1,t,t+1].flatMap(t=>this.options.stores.map(async r=>{let i=await this.read(r,e,`revocation`,t,0,n),a=i===void 0?void 0:Kn(i);if(i===void 0||a===void 0)return;let o=await Promise.all(Array.from({length:a-1},(i,a)=>this.read(r,e,`revocation`,t,a+1,n)));if(!o.some(e=>e===void 0))return qn([i,...o])}));return(await Promise.all(r)).filter(e=>e!==void 0)}advertise(e,t){if(this.closed)return Promise.resolve();this.routes=e;let n=h(this.now()),r=new Set(e.map(e=>e.outbound));for(let[e,t]of this.scheduled)r.has(e)||(clearTimeout(t.timer),this.scheduled.delete(e));this.prefetchedEpoch!==n&&(this.prefetchedEpoch=n,this.findLists(AbortSignal.timeout(3e4)));let i=this.options.maxPublishJitterMs??9e4;for(let r of e){let e=this.scheduled.get(r.outbound);if(e!==void 0&&e.epoch===n&&e.port===t)continue;e!==void 0&&clearTimeout(e.timer);let a=setTimeout(()=>{this.scheduled.delete(r.outbound),this.publish(r,t)},rr(i,this.options.random));a.unref?.(),this.scheduled.set(r.outbound,{timer:a,epoch:n,port:t})}return Promise.resolve()}async publish(e,t){if(this.closed)return;let n=this.now(),r=h(n),i=[];try{i.push({purpose:`hints`,chunk:0,plaintext:Qn(this.options.addresses().map(e=>({host:e,port:t})),this.options.relayEndpoints?.()??[])});let e=this.options.lists?.();if(e!==void 0){let t=await Gn({r:e.revocation,...e.signingKeyRevocation===void 0?{}:{s:e.signingKeyRevocation}});for(let[e,n]of t.entries())i.push({purpose:`revocation`,chunk:e,plaintext:n})}}catch(e){this.options.onError?.(or(e))}for(let{purpose:t,chunk:a,plaintext:o}of i)try{let i=await e.rendezvous.sealRecord(o,r,t),s=await Wn(e.rendezvous,t,`outbound`,r,a),c=await Promise.allSettled(this.options.stores.map(e=>e.put(s,i,n)));for(let e of c)e.status===`rejected`&&this.options.onError?.(or(e.reason))}catch(e){this.options.onError?.(or(e))}}async latestLists(e){let t=new Promise(t=>{e.aborted&&t(void 0),e.addEventListener(`abort`,()=>t(void 0),{once:!0})});return await Promise.race([this.findLists(e),t])??this.listsFound}async findLists(e){let t=h(this.now()),n=await Promise.all(this.routes.slice(0,16).map(n=>this.lookupLists(n,t,e))),r=[],i=[];for(let e of n){let t=[],n=[];for(let r of e){if(typeof r!=`object`||!r)continue;let e=r;e.r!==void 0&&t.push(e.r),e.s!==void 0&&n.push(e.s)}r.push(t),i.push(n)}let a=ur(r),o=ur(i),s=a.length===0&&o.length===0?void 0:{...a.length>0?{revocation:a}:{},...o.length>0?{signingKeyRevocation:o}:{}};return e.aborted||(this.listsFound=s),s}close(){if(!this.closed){this.closed=!0;for(let{timer:e}of this.scheduled.values())clearTimeout(e);this.scheduled.clear();for(let e of this.options.stores)e.close()}}};function cr(e){let t=new Set;return e.filter(e=>{let n=JSON.stringify(e);return t.has(n)?!1:(t.add(n),!0)})}function lr(e){return cr(e).sort((e,t)=>ar(t)-ar(e))}function ur(e){let t=e.map(e=>lr(e).slice(0,2)),n=[];for(let e=0;e<2;e+=1)n.push(...lr(t.flatMap(t=>t.slice(e,e+1))));return cr(n).slice(0,16)}function dr(e){let t=``;for(let n of e)t+=n.toString(16).padStart(2,`0`);return t}function fr(){let e=new Map,t=e=>e,n=(e,t)=>`${dr(e)}/${dr(t??new Uint8Array)}`;return{store:()=>({async put(t,r,i){let a=await Vn(t.key,t.salt,Math.floor(i/1e3),r);if(!await Z(a,a.k,a.salt))throw Error(`item refused`);let o=n(a.k,a.salt),s=e.get(o);if(s!==void 0&&s.seq>a.seq)throw Error(`item refused: older seq`);e.set(o,a)},async get(r,i){await Promise.resolve();let a=e.get(n(r,i)),o=a===void 0?void 0:t(a);if(o!==void 0)return await Z(o,r,i)?o.v:void 0},close:()=>void 0}),items:()=>[...e.values()],serve:e=>{t=e}}}const pr=`ybndrfg8ejkmcpqxot1uwisza345h769`;function mr(e){let t=``,n=0,r=0;for(let i of e)for(n=n<<8|i,r+=8;r>=5;)t+=pr[n>>>r-5&31],r-=5;return r>0&&(t+=pr[n<<5-r&31]),t}function hr(e){return Uint8Array.from([e>>>8&255,e&255])}function gr(e,t){let n=Y([...[`_r`,mr(e)].flatMap(e=>[Uint8Array.of(e.length),new TextEncoder().encode(e)]),Uint8Array.of(0)]),r=[];for(let e=0;e<t.length;e+=255){let n=t.subarray(e,e+255);r.push(Uint8Array.of(n.length),n)}t.length===0&&r.push(Uint8Array.of(0));let i=Y(r);return Y([Uint8Array.from([0,0,132,0,0,0,0,1,0,0,0,0]),n,hr(16),hr(1),Uint8Array.from([0,0,1,44]),hr(i.length),i])}function _r(e){let t=t=>(e[t]??0)<<8|(e[t+1]??0);if(e.length<12)return;let n=t(4),r=t(6),i=12,a=()=>{for(let t=0;t<128;t+=1){let t=e[i];if(t===void 0)return!1;if(t===0)return i+=1,!0;if((t&192)==192)return i+=2,!0;i+=1+t}return!1};for(let e=0;e<n;e+=1){if(!a())return;i+=4}for(let n=0;n<r;n+=1){if(!a()||i+10>e.length)return;let n=t(i),r=t(i+8),o=i+10,s=o+r;if(s>e.length)return;if(n===16){let t=[],n=o;for(;n<s;){let r=e[n];if(n+1+r>s)return;t.push(e.subarray(n+1,n+1+r)),n+=1+r}return Y(t)}i=s}}function vr(e){let t=new Uint8Array(8);return new DataView(t.buffer).setBigUint64(0,BigInt(e)),t}function yr(e){let t=e.length;for(;t>0&&e[t-1]===`/`;)--t;return e.slice(0,t)}function br(e){let t=e.fetch??globalThis.fetch.bind(globalThis),n=(e,t)=>`${yr(e)}/${mr(t)}`;return{async put(r,i,a,o){let s=gr(r.key.publicKey,i);if(s.length>999)throw Error(`record too large for a pkarr relay`);let c=Math.floor(a)*1e3,l=Y([await r.key.sign(X(void 0,c,s)),vr(c),s]);if(!(await Promise.allSettled(e.relays.map(async e=>{let i=await t(n(e,r.key.publicKey),{method:`PUT`,headers:{"content-type":`application/pkarr.org/relays#payload`},body:l.slice().buffer,...o===void 0?{}:{signal:o}});if(!i.ok)throw Error(`pkarr relay refused (${i.status})`)}))).some(e=>e.status===`fulfilled`))throw Error(`no pkarr relay took the record`)},async get(r,i,a){let o=await Promise.all(e.relays.map(async e=>{try{let i=await t(n(e,r),{signal:a});if(!i.ok)return;let o=new Uint8Array(await i.arrayBuffer());if(o.length<=72||o.length>1200)return;let s=o.subarray(0,64),c=Number(new DataView(o.buffer,o.byteOffset+64,8).getBigUint64(0)),l=o.slice(72);if(!Number.isSafeInteger(c)||!await Bn(r,X(void 0,c,l),s))return;let u=_r(l);return u===void 0?void 0:{seq:c,value:u}}catch{return}})),s;for(let e of o)e!==void 0&&(s===void 0||e.seq>s.seq)&&(s=e);return s?.value},close:()=>void 0}}const xr=Uint8Array.from([48,42,48,5,6,3,43,101,112,3,33,0]),Sr=(e,t,n)=>{if(n.length!==32||e.length!==64)return!1;try{return de(null,t,ce({key:Buffer.from(Y([xr,n])),format:`der`,type:`spki`}),e)}catch{return!1}};async function Cr(e){return new(await(import(`bittorrent-dht`))).default({verify:e})}function Q(e){return Buffer.from(e.buffer,e.byteOffset,e.byteLength)}function wr(e){if(e!==void 0)return new Promise((t,n)=>{e.aborted&&n(Error(`aborted`)),e.addEventListener(`abort`,()=>n(Error(`aborted`)),{once:!0})})}async function Tr(e={}){let t=await(e.createDht??Cr)(Sr),n=t=>e.onError?.(t);t.on(`error`,n),t.on(`warning`,n);let r=!1;return{async put(e,n,i,a){if(r)throw Error(`DHT store closed`);if(n.length>999)throw Error(`record value exceeds 999 bytes`);let o=await Vn(e.key,e.salt,Math.floor(i/1e3),n),s=new Promise((n,r)=>{t.put({k:Q(o.k),salt:Q(e.salt),seq:o.seq,v:Q(o.v),sig:Q(o.sig)},(e,t,i)=>{e===null?i===0?r(Error(`no DHT node took the record`)):n():r(e)})}),c=wr(a);await(c===void 0?s:Promise.race([s,c]))},async get(e,n,i){if(r||i.aborted)return;let a=_(`sha1`).update(Y([e,n])).digest(),o=new Promise(e=>{t.get(a,{salt:Q(n),cache:!1},(t,n)=>e(t===null?n:null))});try{let t=await Promise.race([o,wr(i)]);if(t?.v===void 0||t.k===void 0||t.sig===void 0)return;let r={k:new Uint8Array(t.k),salt:n,seq:t.seq??0,v:new Uint8Array(t.v),sig:new Uint8Array(t.sig)};return await Z(r,e,n)?r.v:void 0}catch{return}},close(){r||(r=!0,t.destroy())}}}const Er=/^[0-9a-f]{64}$/,Dr=/^[0-9a-f]{128}$/;function Or(e){return 2e4+((e[0]??0)<<8|(e[1]??0))%1e4}function kr(e){let t=``;for(let n of e)t+=String.fromCharCode(n);return btoa(t)}function Ar(e){try{let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e+=1)n[e]=t.charCodeAt(e);return n}catch{return}}function jr(e){if(typeof e!=`object`||!e)return;let t=e;if(!(typeof t.id!=`string`||!Er.test(t.id))&&!(typeof t.pubkey!=`string`||!Er.test(t.pubkey))&&!(typeof t.sig!=`string`||!Dr.test(t.sig))&&!(typeof t.kind!=`number`||!Number.isInteger(t.kind))&&!(typeof t.created_at!=`number`||!Number.isInteger(t.created_at))&&!(typeof t.content!=`string`||t.content.length>49152)&&!(!Array.isArray(t.tags)||t.tags.length!==0))return{id:t.id,pubkey:t.pubkey,sig:t.sig,kind:t.kind,created_at:t.created_at,content:t.content,tags:[]}}var Mr=class{options;messages=new Set;absents=new Set;outbound=new Map;inbound=new Map;subscription;chain=Promise.resolve();seen=new Set;routes=[];epoch;timer;closed=!1;constructor(e){this.options=e}now(){return(this.options.now??Date.now)()}report(e){this.options.onError?.(e instanceof Error?e:Error(String(e)))}enqueue(e){this.chain=this.chain.then(e).catch(e=>this.report(e))}whenIdle(){return this.chain}declarePresence(){}declarePeers(e){this.enqueue(()=>this.derive(e))}async derive(e){if(this.closed)return;this.routes=e;let t=h(this.now()),n=new Map,r=new Map;for(let i of e){let e=await i.rendezvous.signingSeed(`outbound`,t,`signal`),a=Or(await i.rendezvous.tag(`nostr-kind`,`outbound`,t));n.set(i.outbound,{route:i,epoch:t,secretKey:e,kind:a});for(let e of[t-1,t,t+1]){let t=await i.rendezvous.signingSeed(`inbound`,e,`signal`),n=Or(await i.rendezvous.tag(`nostr-kind`,`inbound`,e));r.set(ge(t),{route:i,epoch:e,kind:n})}}this.closed||(this.outbound=n,this.inbound=r,this.epoch=t,this.subscription?.close(),this.subscription=r.size===0?void 0:this.options.pool.subscribe({kinds:[...new Set([...r.values()].map(e=>e.kind))],authors:[...r.keys()],since:Math.floor(this.now()/1e3)-(this.options.maxEventAgeS??120)},e=>this.enqueue(()=>this.receive(e))),this.timer!==void 0&&clearTimeout(this.timer),this.timer=setTimeout(()=>this.declarePeers(this.routes),Math.max(0,(t+1)*a-this.now())),this.timer.unref?.())}send(e,t){this.closed||this.enqueue(async()=>{if(this.closed)return;this.epoch!==void 0&&h(this.now())!==this.epoch&&await this.derive(this.routes);let n=this.outbound.get(e);if(n===void 0){for(let t of this.absents)t(e);return}let r=new TextEncoder().encode(JSON.stringify(t)).length;if(r>32768)throw Error(`signal too large for a Nostr event`);let i=Yn(t,Math.ceil(r/512)*512),a=await n.route.rendezvous.sealRecord(i,n.epoch,`signal`),o=he({kind:n.kind,created_at:Math.floor(this.now()/1e3),tags:[],content:kr(a)},n.secretKey);if(!await this.options.pool.publish(o))throw Error(`no Nostr relay took the signal`)})}async receive(e){if(this.closed)return;let t=jr(e);if(t===void 0||this.seen.has(t.id))return;let n=this.inbound.get(t.pubkey);if(n===void 0||t.kind!==n.kind||Math.abs(Math.floor(this.now()/1e3)-t.created_at)>(this.options.maxEventAgeS??120)||!_e(t))return;this.remember(t.id);let r=Ar(t.content);if(r===void 0)return;let i=await n.route.rendezvous.openRecord(r,n.epoch,`signal`);if(i?.epoch!==n.epoch)return;let a=Xn(i.hints);if(!(a===void 0||this.closed))for(let e of this.messages)e(n.route.inbound,a)}remember(e){if(this.seen.add(e),this.seen.size<=2048)return;let t=this.seen.values().next().value;t!==void 0&&this.seen.delete(t)}onMessage(e){return this.messages.add(e),()=>this.messages.delete(e)}onAbsent(e){return this.absents.add(e),()=>this.absents.delete(e)}close(){this.closed||(this.closed=!0,this.timer!==void 0&&clearTimeout(this.timer),this.subscription?.close(),this.messages.clear(),this.absents.clear(),this.options.pool.close())}};function Nr(e,t){return e.kinds.includes(t.kind)&&e.authors.includes(t.pubkey)}function Pr(){let e=new Set,t=[],n=t=>{let n=JSON.parse(JSON.stringify(t));queueMicrotask(()=>{for(let t of[...e])Nr(t.filter,n)&&t.onEvent(n)})};return{pool:()=>{let r=new Set;return{publish:e=>{let r=jr(e);return r===void 0||!_e(r)?Promise.resolve(!1):(t.push(JSON.parse(JSON.stringify(e))),n(e),Promise.resolve(!0))},subscribe:(t,n)=>{let i={filter:t,onEvent:n};return e.add(i),r.add(i),{close:()=>{e.delete(i),r.delete(i)}}},close:()=>{for(let t of r)e.delete(t);r.clear()}}},events:t,inject:e=>n(e)}}function Fr(e){if(e.length===0)throw Error(`a Nostr relay pool needs at least one relay`);let t=new me,n=[...e];return{publish:async e=>(await Promise.allSettled(t.publish(n,e))).some(e=>e.status===`fulfilled`),subscribe:(e,r)=>t.subscribeMany(n,{kinds:[...e.kinds],authors:[...e.authors],...e.since===void 0?{}:{since:e.since}},{onevent:e=>r(e)}),close:()=>t.destroy()}}const Ir=[`wss://relay.damus.io`,`wss://nos.lol`,`wss://relay.primal.net`],Lr=[`https://pkarr.pubky.app`,`https://pkarr.pubky.org`,`https://dns.iroh.link/pkarr`],Rr=/^[A-Za-z0-9_-]{22}$/;var $=class extends Error{reason;constructor(e,t){super(`enrollment connection failed (${e})${t===void 0?``:`: ${t}`}`),this.name=`EnrollmentLinkError`,this.reason=e}};function zr(e,t){return typeof e==`string`&&e.length>0&&e.length<=t}function Br(e){if(typeof e!=`object`||!e||Array.isArray(e))return;let t=e;if(t.v!==1||typeof t.cid!=`string`||!Rr.test(t.cid))return;let n=t.cid;if(t.kind===`offer`||t.kind===`answer`)return zr(t.sdp,49152)?{kind:t.kind,cid:n,sdp:t.sdp}:void 0;if(t.kind===`ice`){let e=t.candidate;if(typeof e!=`object`||!e||Array.isArray(e))return;let r=e;return!zr(r.candidate,2048)||!zr(r.mid,64)?void 0:{kind:`ice`,cid:n,candidate:{candidate:r.candidate,mid:r.mid}}}}function Vr(){let e=new Uint8Array(16);return globalThis.crypto.getRandomValues(e),Buffer.from(e).toString(`base64url`)}var Hr=class{role;cid;options;onBound;onFailed;peer;channel;localFingerprint;remoteFingerprint;tookRemoteDescription=!1;sentDescription=!1;localCandidates=[];remoteCandidates=0;chain=Promise.resolve();stopAwaiting;timer;done=!1;early=[];frameHandlers=new Set;closeHandlers=new Set;constructor(e,t,n,r,i){this.role=e,this.cid=t,this.options=n,this.onBound=r,this.onFailed=i,this.timer=setTimeout(()=>this.fail(new $(`timeout`)),n.connectTimeoutMs??2e4)}async offer(){try{let e=this.createPeer();this.adopt(e.createDataChannel(`agent-enroll`));let t=await e.createOffer();if(this.done)return;this.localFingerprint=p(t),this.sendDescription({kind:`offer`,cid:this.cid,sdp:t})}catch(e){this.fail(new $(`signaling`,Ur(e)))}}onSignal(e){this.done||(this.chain=this.chain.then(()=>this.apply(e)).catch(e=>this.fail(new $(`signaling`,Ur(e)))))}async apply(e){if(this.done)return;if(e.kind===`ice`){if(this.peer===void 0||++this.remoteCandidates>64)return;this.peer.addRemoteCandidate(e.candidate);return}let t=this.role===`offerer`?`answer`:`offer`;if(e.kind!==t||this.tookRemoteDescription)return;this.tookRemoteDescription=!0;let n;try{n=m(e.sdp).algorithm}catch(e){this.fail(new $(`channel-binding`,Ur(e)));return}if(this.role===`offerer`){let t=this.peer;if(t===void 0)return;t.acceptAnswer(e.sdp),this.awaitCertificate(t,n);return}let r=this.createPeer(),i=await r.acceptOffer(e.sdp);this.done||(this.localFingerprint=p(i),this.sendDescription({kind:`answer`,cid:this.cid,sdp:i}),this.awaitCertificate(r,n))}createPeer(){let e=new T({...this.options.iceServers===void 0?{}:{iceServers:this.options.iceServers},...this.options.loadDataChannel===void 0?{}:{loadDataChannel:this.options.loadDataChannel}});return this.peer=e,e.onLocalCandidate(e=>{if(this.done)return;let t={kind:`ice`,cid:this.cid,candidate:{candidate:e.candidate,mid:e.mid}};this.sentDescription?this.send(t):this.localCandidates.length<64&&this.localCandidates.push(t)}),e.onStateChange(e=>{(e===`failed`||e===`closed`)&&this.fail(new $(`closed`,`connection ${e}`))}),e.onDataChannel(e=>{this.role===`answerer`&&this.channel===void 0&&!this.done?this.adopt(e):e.close()}),e}send(e){this.options.relay.send(this.options.outbound,{v:1,...e})}sendDescription(e){this.send(e),this.sentDescription=!0;for(let e of this.localCandidates.splice(0))this.send(e)}awaitCertificate(e,t){this.stopAwaiting=S(e,t,e=>{this.remoteFingerprint=e,this.maybeBound()},e=>this.fail(new $(`channel-binding`,e)))}adopt(e){this.channel=e,e.onMessage(e=>this.inbound(e)),e.onStateChange(e=>{e===`open`?this.maybeBound():e===`closed`&&this.closed()}),e.readyState===`open`&&this.maybeBound()}inbound(e){if(e.length>262144){this.closeAll();return}if(this.frameHandlers.size===0){if(this.early.length>=16){this.closeAll();return}this.early.push(e);return}this.deliver(e)}deliver(e){let t;try{t=JSON.parse(e)}catch{t=void 0}for(let e of this.frameHandlers)e(t)}maybeBound(){let e=this.channel;if(this.done||e===void 0||e.readyState!==`open`)return;let t=this.localFingerprint,n=this.remoteFingerprint;t!==void 0&&n!==void 0&&(this.done=!0,clearTimeout(this.timer),this.stopAwaiting?.(),this.onBound({localFingerprint:t,remoteFingerprint:n,send:t=>{try{e.send(JSON.stringify(t))}catch{}},onFrame:e=>{this.frameHandlers.add(e);let t=this.early.splice(0);return t.length>0&&queueMicrotask(()=>t.forEach(e=>this.deliver(e))),()=>this.frameHandlers.delete(e)},onClose:t=>e.readyState===`closed`?(queueMicrotask(t),()=>void 0):(this.closeHandlers.add(t),()=>this.closeHandlers.delete(t)),close:()=>this.closeAll()}))}closed(){if(!this.done){this.fail(new $(`closed`,`data channel closed`));return}this.closeAll()}closeAll(){this.channel?.close();let e=this.peer;e!==void 0&&setTimeout(()=>e.close(),250).unref?.();let t=[...this.closeHandlers];this.closeHandlers.clear(),this.frameHandlers.clear();for(let e of t)e()}fail(e){this.done||(this.done=!0,clearTimeout(this.timer),this.stopAwaiting?.(),this.channel?.close(),this.peer?.close(),this.onFailed(e))}};function Ur(e){return e instanceof Error?e.message:String(e)}function Wr(e){return new Promise((t,n)=>{let r=[],i=()=>{for(let e of r.splice(0))e()},a=new Hr(`offerer`,Vr(),e,e=>{i(),t(e)},e=>{i(),n(e)});r.push(e.relay.onMessage((t,n)=>{if(t!==e.inbound)return;let r=Br(n);r!==void 0&&r.cid===a.cid&&a.onSignal(r)}),e.relay.onAbsent(t=>{t===e.outbound&&a.fail(new $(`absent`))})),e.relay.declarePresence([e.inbound]),a.offer()})}function Gr(e){let t,n=!1,r=e.relay.onMessage((r,i)=>{if(n||r!==e.inbound)return;let a=Br(i);if(a===void 0)return;if(t!==void 0){a.cid===t.cid&&t.onSignal(a);return}if(a.kind!==`offer`)return;let o=new Hr(`answerer`,a.cid,e,r=>{if(n){r.close();return}r.onClose(()=>{t===o&&(t=void 0)}),e.onChannel(r)},n=>{t===o&&(t=void 0),e.onAttemptFailed?.(n)});t=o,o.onSignal(a)});return e.relay.declarePresence([e.inbound]),{close:()=>{n||(n=!0,r(),t?.fail(new $(`closed`,`no longer listening`)))}}}export{ir as DEFAULT_MAX_PUBLISH_JITTER_MS,Ir as DEFAULT_NOSTR_RELAYS,Lr as DEFAULT_PKARR_RELAYS,Ft as DEFAULT_RELAY_CREDENTIAL_TTL_MS,xt as DEFAULT_TURN_QUOTAS,St as DEFAULT_UNAUTHENTICATED_LIMITS,tn as DeviceMeshNode,Nn as DiscoveringMeshRelay,$ as EnrollmentLinkError,an as MAX_CACHED_CANDIDATES,$e as MAX_MESH_MESSAGE_CHARS,It as MAX_RELAY_CREDENTIAL_TTL_MS,G as MESH_MDNS_SERVICE,sr as MeshDht,nt as MeshLinkEndedError,wn as MeshMdns,B as MeshRelayNeededError,Ht as MeshTurnRelay,Mr as NostrMeshRelay,w as RtcChannel,T as RtcPeer,Pt as TurnServer,Ke as WebRtcTransport,rn as WsMeshRelayClient,Ze as WsSignalingClient,on as addressCacheSource,fr as createInMemoryItemNetwork,Tn as createInMemoryMdnsBus,ln as createInMemoryMeshAddressCache,nn as createInMemoryMeshRelayHub,Pr as createInMemoryNostrHub,Je as createInMemorySignalingPair,Fr as createNostrRelayPool,br as createPkarrRelayStore,Wr as dialEnrollment,ke as handoffGrantFrame,Oe as judgeHandoffGrant,Gr as listenForEnrollment,xe as loadDataChannel,bn as localInterfaceAddresses,Ne as localProofFrame,zt as meshRelayCredential,Vt as meshRelayIceServers,Cn as paddedInstanceCount,Pn as startLanMeshRelay,Tr as startMainlineDhtStore,vn as startMeshLanListener};
2
2
  //# sourceMappingURL=index.js.map