@pulsebeam/peer 0.0.21 → 0.0.22
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.
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
@@ -33,5 +33,5 @@ t=0 0\r
|
|
33
33
|
a=extmap-allow-mixed`)!==-1){let s=i.sdp.split(`
|
34
34
|
`).filter(a=>a.trim()!=="a=extmap-allow-mixed").join(`
|
35
35
|
`);e.RTCSessionDescription&&i instanceof e.RTCSessionDescription?arguments[0]=new e.RTCSessionDescription({type:i.type,sdp:s}):i.sdp=s}return n.apply(this,arguments)}}function I(e,t){if(!(e.RTCPeerConnection&&e.RTCPeerConnection.prototype))return;let n=e.RTCPeerConnection.prototype.addIceCandidate;!n||n.length===0||(e.RTCPeerConnection.prototype.addIceCandidate=function(){return arguments[0]?(t.browser==="chrome"&&t.version<78||t.browser==="firefox"&&t.version<68||t.browser==="safari")&&arguments[0]&&arguments[0].candidate===""?Promise.resolve():n.apply(this,arguments):(arguments[1]&&arguments[1].apply(null),Promise.resolve())})}function E(e,t){if(!(e.RTCPeerConnection&&e.RTCPeerConnection.prototype))return;let n=e.RTCPeerConnection.prototype.setLocalDescription;!n||n.length===0||(e.RTCPeerConnection.prototype.setLocalDescription=function(){let i=arguments[0]||{};if(typeof i!="object"||i.type&&i.sdp)return n.apply(this,arguments);if(i={type:i.type,sdp:i.sdp},!i.type)switch(this.signalingState){case"stable":case"have-local-offer":case"have-remote-pranswer":i.type="offer";break;default:i.type="answer";break}return i.sdp||i.type!=="offer"&&i.type!=="answer"?n.apply(this,[i]):(i.type==="offer"?this.createOffer:this.createAnswer).apply(this).then(a=>n.apply(this,[a]))})}var Dt=nt(Pe());function ft({window:e}={},t={shimChrome:!0,shimFirefox:!0,shimSafari:!0}){let n=O,r=pt(e),i={browserDetails:r,commonShim:xe,extractVersion:b,disableLog:at,disableWarnings:ct,sdp:Dt};switch(r.browser){case"chrome":if(!j||!A||!t.shimChrome)return n("Chrome shim is not included in this adapter release."),i;if(r.version===null)return n("Chrome shim can not determine version, not shimming."),i;n("adapter.js shimming chrome."),i.browserShim=j,I(e,r),E(e,r),L(e,r),ee(e,r),A(e,r),te(e,r),ie(e,r),re(e,r),ne(e,r),se(e,r),P(e,r),q(e,r),z(e,r),x(e,r),k(e,r),B(e,r);break;case"firefox":if(!N||!F||!t.shimFirefox)return n("Firefox shim is not included in this adapter release."),i;n("adapter.js shimming firefox."),i.browserShim=N,I(e,r),E(e,r),U(e,r),F(e,r),oe(e,r),pe(e,r),ae(e,r),ce(e,r),de(e,r),le(e,r),ue(e,r),me(e,r),fe(e,r),P(e,r),z(e,r),x(e,r),k(e,r);break;case"safari":if(!G||!t.shimSafari)return n("Safari shim is not included in this adapter release."),i;n("adapter.js shimming safari."),i.browserShim=G,I(e,r),E(e,r),Se(e,r),ve(e,r),Ce(e,r),he(e,r),ge(e,r),Re(e,r),ye(e,r),Te(e,r),P(e,r),q(e,r),x(e,r),k(e,r),B(e,r);break;default:n("Unsupported browser!");break}return i}var Ot=ft({window:typeof window>"u"?void 0:window}),_=Ot;import{ServiceType as Lt}from"@protobuf-ts/runtime-rpc";import{MessageType as h}from"@protobuf-ts/runtime";var Xe=(s=>(s[s.UNSPECIFIED=0]="UNSPECIFIED",s[s.OFFER=1]="OFFER",s[s.ANSWER=2]="ANSWER",s[s.PRANSWER=3]="PRANSWER",s[s.ROLLBACK=4]="ROLLBACK",s))(Xe||{}),ke=class extends h{constructor(){super("pulsebeam.v1.PrepareReq",[])}},At=new ke,Ie=class extends h{constructor(){super("pulsebeam.v1.PrepareResp",[{no:1,name:"ice_servers",kind:"message",repeat:1,T:()=>Ut}])}},jt=new Ie,Ee=class extends h{constructor(){super("pulsebeam.v1.IceServer",[{no:1,name:"urls",kind:"scalar",repeat:2,T:9},{no:2,name:"username",kind:"scalar",opt:!0,T:9},{no:3,name:"credential",kind:"scalar",opt:!0,T:9}])}},Ut=new Ee,_e=class extends h{constructor(){super("pulsebeam.v1.SendReq",[{no:1,name:"msg",kind:"message",T:()=>ht}])}},Ft=new _e,Me=class extends h{constructor(){super("pulsebeam.v1.SendResp",[])}},Nt=new Me,De=class extends h{constructor(){super("pulsebeam.v1.RecvReq",[{no:1,name:"src",kind:"message",T:()=>Ae}])}},Gt=new De,Oe=class extends h{constructor(){super("pulsebeam.v1.RecvResp",[{no:1,name:"msg",kind:"message",T:()=>ht}])}},qt=new Oe,Le=class extends h{constructor(){super("pulsebeam.v1.PeerInfo",[{no:1,name:"group_id",kind:"scalar",T:9},{no:2,name:"peer_id",kind:"scalar",T:9},{no:3,name:"conn_id",kind:"scalar",T:13}])}},Ae=new Le,je=class extends h{constructor(){super("pulsebeam.v1.Message",[{no:1,name:"header",kind:"message",T:()=>Bt},{no:2,name:"payload",kind:"message",T:()=>zt}])}},ht=new je,Ue=class extends h{constructor(){super("pulsebeam.v1.MessagePayload",[{no:1,name:"signal",kind:"message",oneof:"payloadType",T:()=>Kt},{no:2,name:"join",kind:"message",oneof:"payloadType",T:()=>Ht},{no:3,name:"bye",kind:"message",oneof:"payloadType",T:()=>Yt},{no:4,name:"ack",kind:"message",oneof:"payloadType",T:()=>Wt},{no:5,name:"ping",kind:"message",oneof:"payloadType",T:()=>Xt}])}},zt=new Ue,Fe=class extends h{constructor(){super("pulsebeam.v1.MessageHeader",[{no:1,name:"src",kind:"message",T:()=>Ae},{no:2,name:"dst",kind:"message",T:()=>Ae},{no:7,name:"seqnum",kind:"scalar",T:13},{no:8,name:"reliable",kind:"scalar",T:8}])}},Bt=new Fe,Ne=class extends h{constructor(){super("pulsebeam.v1.Signal",[{no:1,name:"generation_counter",kind:"scalar",T:13},{no:9,name:"sdp",kind:"message",oneof:"data",T:()=>Jt},{no:10,name:"ice_candidate",kind:"message",oneof:"data",T:()=>gt},{no:11,name:"ice_candidate_batch",kind:"message",oneof:"data",T:()=>Vt}])}},Kt=new Ne,Ge=class extends h{constructor(){super("pulsebeam.v1.Sdp",[{no:1,name:"kind",kind:"enum",T:()=>["pulsebeam.v1.SdpKind",Xe,"SDP_KIND_"]},{no:2,name:"sdp",kind:"scalar",T:9}])}},Jt=new Ge,qe=class extends h{constructor(){super("pulsebeam.v1.ICECandidateBatch",[{no:1,name:"candidates",kind:"message",repeat:1,T:()=>gt}])}},Vt=new qe,ze=class extends h{constructor(){super("pulsebeam.v1.ICECandidate",[{no:1,name:"candidate",kind:"scalar",T:9},{no:2,name:"sdp_m_line_index",kind:"scalar",opt:!0,T:13},{no:3,name:"sdp_mid",kind:"scalar",opt:!0,T:9},{no:4,name:"username",kind:"scalar",opt:!0,T:9},{no:5,name:"password",kind:"scalar",opt:!0,T:9}])}},gt=new ze,Be=class extends h{constructor(){super("pulsebeam.v1.Join",[])}},Ht=new Be,Ke=class extends h{constructor(){super("pulsebeam.v1.Bye",[])}},Yt=new Ke,Je=class extends h{constructor(){super("pulsebeam.v1.Ack",[{no:1,name:"ack_ranges",kind:"message",repeat:1,T:()=>Qt}])}},Wt=new Je,Ve=class extends h{constructor(){super("pulsebeam.v1.Ping",[])}},Xt=new Ve,He=class extends h{constructor(){super("pulsebeam.v1.AckRange",[{no:1,name:"seqnum_start",kind:"scalar",T:13},{no:2,name:"seqnum_end",kind:"scalar",T:13}])}},Qt=new He,Ye=class extends h{constructor(){super("pulsebeam.v1.DataChannel",[{no:10,name:"heartbeat",kind:"message",oneof:"payload",T:()=>Zt}])}},Pr=new Ye,We=class extends h{constructor(){super("pulsebeam.v1.DataChannelHeartbeat",[])}},Zt=new We,K=new Lt("pulsebeam.v1.Signaling",[{name:"Prepare",options:{},I:At,O:jt},{name:"Send",options:{},I:Ft,O:Nt},{name:"Recv",serverStreaming:!0,options:{},I:Gt,O:qt}]);import{stackIntercept as Qe}from"@protobuf-ts/runtime-rpc";var J=class{constructor(t){this._transport=t;this.typeName=K.typeName;this.methods=K.methods;this.options=K.options}prepare(t,n){let r=this.methods[0],i=this._transport.mergeOptions(n);return Qe("unary",this._transport,r,i,t)}send(t,n){let r=this.methods[1],i=this._transport.mergeOptions(n);return Qe("unary",this._transport,r,i,t)}recv(t,n){let r=this.methods[2],i=this._transport.mergeOptions(n);return Qe("serverStreaming",this._transport,r,i,t)}};function Ze(e,t){return new Promise(n=>{let r=setTimeout(()=>n(!0),e);t&&t.addEventListener("abort",()=>{clearTimeout(r),n(!1)})})}function V(...e){let t=new AbortController,n=()=>{t.abort();for(let r of e)r.removeEventListener("abort",n)};for(let r of e)r.addEventListener("abort",n);return t.signal}async function M(e,t){let{maxRetries:n,baseDelay:r,maxDelay:i,jitterFactor:s=.3,isRecoverable:a=()=>!0,abortSignal:o}=t,d=0;for(;(d<=n||n<0)&&!o?.aborted;)try{return await e()}catch(c){if(!a(c)||(d++,n>=0&&d>n))throw c;let p=$t(d,r,i,s);await Ze(p,o).catch(()=>{})}if(o?.aborted)return null;throw new Error("Retry failed: max retries exceeded")}function $t(e,t,n,r){let i=Math.min(t*2**(e-1),n),s=Math.random()*r*i;return i+s}var Ct=9e5,yt=50,$e=1e3;var wt=Ze,er=e=>{let t;do{let n=new Uint32Array(1);crypto.getRandomValues(n),t=n[0]}while(t>=0&&t<e);return t},tr=e=>!0,we=class{constructor(t){this.onmsg=async t=>{};this.logger=t.sub("queue"),this.map=new Map,this.emitted=new Map,this.unreliable=[],this.processing=!1}enqueue(t){if(!t.header?.reliable)this.unreliable.push(t);else{let n=t.header.seqnum;if(this.map.has(n)||this.emitted.has(n))return;this.map.set(n,[performance.now(),t])}this.processNext()}async processNext(){if(this.processing)return;let t=this.unreliable.pop();if(!t){let n=this.map.entries().next().value;if(!n)return;let[r,i]=n;this.map.delete(r),this.emitted.set(r,i);let[s,a]=i;if(!a.header)return;t=a}this.processing=!0;try{await this.onmsg(t)}catch(n){let r={msg:t};n instanceof Error&&(r.err=n),this.logger.error("error processing message",r)}this.processing=!1,this.processNext()}},H=class{constructor(t,n){this.client=t;this.opts=n;this.onstream=t=>{};this.onclosed=t=>{};this.handleControlMessage=t=>{switch(t.payloadType.oneofKind){case"ping":this.logger.debug("received ping");break;default:this.logger.warn("received unknown control message",{payload:t});break}};this.handleMessages=t=>{if(this.logger.debug("received",{msg:t}),this.abort.signal.aborted)return;if(!t.header)return t.payload?this.handleControlMessage(t.payload):void 0;let n=t.header.src,r=t.header.dst;if(!n||!r)return;if(r.connId>=16&&r.connId!=this.info.connId){this.logger.warn("received messages from a stale connection, ignoring",{receivedConnID:r.connId});return}let i=null;for(let s of this.streams)if(n.groupId===s.other.groupId&&n.peerId===s.other.peerId&&n.connId===s.other.connId){i=s;break}if(!i){if(n.peerId==this.info.peerId){this.logger.warn("loopback detected, ignoring messages");return}this.logger.debug(`session not found, creating one for ${n.peerId}:${n.connId}`),i=new et(this,this.info,n,this.logger),this.streams.push(i),this.onstream(i)}i.enqueue(t)};this.asleep=n.asleep||wt,this.randUint32=n.randUint32||er,this.isRecoverable=n.isRecoverable||tr,this.info={groupId:n.groupId,peerId:n.peerId,connId:this.randUint32(16)},this.abort=new AbortController,this.logger=n.logger.sub("transport",{info:this.info}),this.streams=[]}async listen(){let t={abort:this.abort.signal,timeout:Ct},n={baseDelay:yt,maxDelay:$e,maxRetries:-1,abortSignal:this.abort.signal,isRecoverable:this.isRecoverable};for(;!this.abort.signal.aborted;)try{await M(async()=>{let r=this.client.recv({src:this.info},t);r.responses.onMessage(i=>!!i.msg&&this.handleMessages(i.msg)),await r},n)}catch(r){this.logger.error("unrecoverable error, force closing",{err:r}),this.close();return}this.logger.debug("poll loop is closed")}async close(t){this.abort.signal.aborted||(t=t||"transport is closed",await Promise.all(this.streams.map(n=>n.close(t))),this.abort.abort(t),this.logger.debug("transport is now closed",{reason:t}),this.streams=[],this.onclosed(t))}removeStream(t){this.streams=this.streams.filter(n=>n!==t)}async connect(t,n,r){let i={payloadType:{oneofKind:"join",join:{}}},s={src:this.info,dst:{groupId:t,peerId:n,connId:0},seqnum:0,reliable:!1},a=!1,o=V(r,this.abort.signal);for(;!o.aborted&&!a;)await this.send(o,{header:s,payload:i}),await this.asleep($e,o).catch(()=>{}),a=!!this.streams.find(d=>d.other.groupId===t&&d.other.peerId===n)}async send(t,n){let r=V(t,this.abort.signal),i={abort:r,timeout:Ct},s={baseDelay:yt,maxDelay:$e,maxRetries:-1,abortSignal:r,isRecoverable:this.isRecoverable};try{if(await M(async()=>await this.client.send({msg:n},i),s)===null){this.logger.warn("aborted, message dropped from sending",{msg:n});return}return}catch(a){this.logger.error("unrecoverable error, force closing",{err:a}),this.close();return}}},et=class{constructor(t,n,r,i){this.transport=t;this.info=n;this.other=r;this.onsignal=async t=>{};this.onclosed=t=>{};this.logger=i.sub("stream",{other:r}),this.abort=new AbortController,this.recvq=new we(this.logger),this.recvq.onmsg=s=>this.handleMessage(s),this.lastSeqnum=0}createSignal(...t){return V(this.abort.signal,...t)}enqueue(t){if(this.abort.signal.aborted){this.logger.warn("received a message in closed state, ignoring new messages.");return}this.recvq.enqueue(t)}async send(t,n,r){r||(r=this.abort.signal);let i={header:{src:this.transport.info,dst:this.other,seqnum:this.lastSeqnum,reliable:n},payload:{...t}};this.lastSeqnum++,await this.transport.send(r,i)}async handleMessage(t){if(!t.payload){this.logger.warn("payload is missing from the stream message",{msg:t});return}switch(t.payload.payloadType.oneofKind){case"bye":this.close("received bye",!0);return;case"signal":this.onsignal(t.payload.payloadType.signal);return;case"join":return;default:this.logger.warn("unhandled payload type",{msg:t});return}}async close(t,n){this.abort.signal.aborted||(t=t||"session is closed",n||await this.send({payloadType:{oneofKind:"bye",bye:{}}},!1).catch(r=>this.logger.warn("failed to send bye",{e:r})),this.abort.abort(t),this.transport.removeStream(this),this.onclosed(t),this.logger.debug("sent bye to the other peer",{reason:t}))}};var rr={DEBUG:console.debug,INFO:console.info,WARN:console.warn,ERROR:console.error},St={DEBUG:e=>console.debug(Y(e)),INFO:e=>console.info(Y(e)),WARN:e=>console.warn(Y(e)),ERROR:e=>console.error(Y(e))};function Rt(e,t,n="root",r=new Set){let i=".";if(!r.has(e)){r.add(e);for(let s in e)if(typeof e[s]=="object"&&e[s]!==null){let a=n+i+s;Rt(e[s],t,a,r)}else{let a=t[n]||[];a.push(`${s}=${e[s]}`),t[n]=a}}}function Y(e){let t={};Rt(e,t);let n=[];for(let r in t)n.push(`[${r}] ${t[r].join(" ")}`);return n.join(`
|
36
|
-
`)}var W=class e{constructor(t,n,r){this.name=t;n||(n={}),r||(r=rr),this.sink=r,this.obj={...n,name:t}}log(t,n,r){let i=r||{};t({ts:Date.now(),message:n,...this.obj,...i})}debug(t,n){this.log(this.sink.DEBUG,t,n)}info(t,n){this.log(this.sink.INFO,t,n)}warn(t,n){this.log(this.sink.WARN,t,n)}error(t,n){this.log(this.sink.ERROR,t,n)}sub(t,n){return n||(n={}),new e(this.name+"."+t,{...this.obj,...n},this.sink)}};var nr=2,vt=5e3;function ir(e){return{candidate:e.candidate,sdpMid:e.sdpMid,sdpMLineIndex:e.sdpMLineIndex,usernameFragment:e.password}}function sr(e){switch(e){case 1:return"offer";case 2:return"answer";case 3:return"pranswer";case 4:return"rollback";default:throw new Error(`unexpected kind: ${e}`)}}function Tt(e){switch(e){case"offer":return 1;case"answer":return 2;case"pranswer":return 3;case"rollback":return 4;default:throw new Error(`unexpected sdp type: ${e}`)}}var X=class{constructor(t,n){this.stream=t;this.ondatachannel=()=>{};this.onconnectionstatechange=()=>{};this.ontrack=()=>{};this.triggerIceRestart=()=>{if(!this.impolite)return;let t=performance.now()-this.lastIceRestart;if(t<vt){let n=vt-t,r=window.setTimeout(()=>{this.triggerIceRestart(),this.timers=this.timers.filter(i=>i===r)},n);return}if(this.pc.connectionState!=="connected"){if(this.iceRestartCount>=nr){this.close("detected sustained network failure");return}this.logger.debug("triggered ICE restart"),this.pc.restartIce(),this.generationCounter++,this.iceRestartCount++,this.lastIceRestart=performance.now()}};this.sendSignal=t=>{this.stream.send({payloadType:{oneofKind:"signal",signal:{...t,generationCounter:this.generationCounter}}},!0)};this.handleSignal=async t=>{if(t.generationCounter<this.generationCounter){this.logger.warn("detected staled generationCounter signals, ignoring");return}this.addCandidates(t);let n=t.data;if(t.generationCounter>this.generationCounter){if(this.logger.debug("detected new generationCounter",{otherGenerationCounter:t.generationCounter,generationCounter:this.generationCounter,msg:n}),n.oneofKind==="iceCandidate"){this.logger.warn("expecting an offer but got ice candidates during an ICE restart, adding to pending.",{msg:n});return}this.generationCounter=t.generationCounter}if(n.oneofKind!="sdp")return;let r=n.sdp;this.logger.debug("received a SDP signal",{sdpKind:r.kind});let i=r.kind===1&&(this.makingOffer||this.pc.signalingState!=="stable");if(this.impolite&&i){this.logger.debug("ignored offer");return}if(this.logger.debug("creating an answer"),await this.pc.setRemoteDescription({type:sr(r.kind),sdp:r.sdp}),r.kind===1){if(await this.pc.setLocalDescription(),!this.pc.localDescription){this.logger.error("unexpected null local description");return}this.sendSignal({data:{oneofKind:"sdp",sdp:{kind:Tt(this.pc.localDescription.type),sdp:this.pc.localDescription.sdp}}})}this.checkPendingCandidates()};this.checkPendingCandidates=()=>{if(!["stable","have-local-offer","have-remote-offer"].includes(this.pc.signalingState)||!this.pc.remoteDescription){this.logger.debug("wait for adding pending candidates",{signalingState:this.pc.signalingState,iceConnectionState:this.pc.iceConnectionState,connectionState:this.pc.connectionState,remoteDescription:this.pc.remoteDescription,pendingCandidates:this.pendingCandidates.length});return}for(let n of this.pendingCandidates)!n.candidate||n.candidate===""||(this.pc.addIceCandidate(n).catch(r=>{this.logger.warn("failed to add candidate, skipping.",{candidate:n,e:r})}),this.logger.debug(`added ice: ${n.candidate}`));this.pendingCandidates=[]};this.pc=new RTCPeerConnection(n),this.makingOffer=!1,this.pendingCandidates=[],this.stream.info.connId===this.stream.other.connId?this.impolite=this.stream.info.peerId>this.stream.other.peerId:this.impolite=this.stream.info.connId>this.stream.other.connId,this.abort=new AbortController,this.logger=t.logger.sub("session",{role:this.impolite?"impolite":"polite"}),this.generationCounter=0,this.iceRestartCount=0,this.lastIceRestart=0,this.timers=[],this._connectionState="new",this.iceBatcher=new tt(this.logger,100,s=>this.sendLocalIceCandidates(s)),t.onsignal=s=>this.handleSignal(s),t.onclosed=s=>this.close(s),this.pc.oniceconnectionstatechange=async()=>{let s=await this.pc.getStats(),a=[],o=[],d=[];s.forEach(c=>{c.type==="candidate-pair"?a.push(c):c.type==="local-candidate"?o.push(c):c.type==="remote-candidate"&&d.push(c)}),this.logger.debug("iceconnectionstate changed",{connectionstate:this.pc.connectionState,iceconnectionstate:this.pc.iceConnectionState,local:o,remote:d,pair:a,pending:this.pendingCandidates})};let r=performance.now();this.pc.onconnectionstatechange=s=>{switch(this.logger.debug("connectionstate changed",{connectionstate:this.pc.connectionState,iceconnectionstate:this.pc.iceConnectionState}),this.setConnectionState(this.pc.connectionState,s),this.pc.connectionState){case"connecting":r=performance.now();break;case"connected":{let a=performance.now()-r;this.logger.debug(`it took ${a}ms to connect`),this.iceRestartCount=0;break}case"disconnected":this.triggerIceRestart();break;case"failed":this.triggerIceRestart();break;case"closed":break}};let i=!0;this.pc.onnegotiationneeded=async()=>{if(i){if(!this.impolite){this.stream.send({payloadType:{oneofKind:"join",join:{}}},!0);return}i=!1}try{if(this.makingOffer=!0,this.logger.debug("creating an offer"),await this.pc.setLocalDescription(),!this.pc.localDescription)throw new Error("expect localDescription to be not empty");this.sendSignal({data:{oneofKind:"sdp",sdp:{kind:Tt(this.pc.localDescription.type),sdp:this.pc.localDescription.sdp}}})}catch(s){s instanceof Error&&this.logger.error("failed in negotiating",{err:s})}finally{this.makingOffer=!1}},this.pc.onicecandidate=({candidate:s})=>{this.iceBatcher.addCandidate(s)},this.pc.ondatachannel=(...s)=>{this.ondatachannel&&this.ondatachannel(...s)},this.pc.ontrack=(...s)=>{this.ontrack&&this.ontrack(...s)}}addTrack(...t){return this.pc.addTrack(...t)}removeTrack(...t){return this.pc.removeTrack(...t)}createDataChannel(...t){return this.pc.createDataChannel(...t)}get connectionState(){return this.pc.connectionState}get closeReason(){return this._closeReason}get other(){return{groupId:this.stream.other.groupId,peerId:this.stream.other.peerId,connId:this.stream.other.connId}}close(t){if(this.abort.signal.aborted)return;this.abort.abort(t);for(let r of this.timers)clearTimeout(r);this.timers=[],this.iceBatcher.close(),this.stream.close(),this._closeReason=t,this.pc.close();let n=new Event("connectionstatechange");this.setConnectionState("closed",n),this.logger.debug("session closed",{connectionState:this.connectionState})}sendLocalIceCandidates(t){let n=[];for(let r of t){let i={candidate:"",sdpMLineIndex:0,sdpMid:""};i.candidate=r.candidate,i.sdpMLineIndex=r.sdpMLineIndex??void 0,i.sdpMid=r.sdpMid??void 0,i.username=r.usernameFragment??void 0,n.push(i)}this.sendSignal({data:{oneofKind:"iceCandidateBatch",iceCandidateBatch:{candidates:n}}})}setConnectionState(t,n){t!==this._connectionState&&this.onconnectionstatechange&&this.onconnectionstatechange(n)}addCandidates(t){let n=[];if(t.data.oneofKind==="iceCandidate")n.push(t.data.iceCandidate);else if(t.data.oneofKind==="iceCandidateBatch")n.push(...t.data.iceCandidateBatch.candidates);else return;this.pendingCandidates.push(...n.map(r=>ir(r))),this.checkPendingCandidates()}},tt=class{constructor(t,n,r){this.candidates=[];this.timeoutId=null;this.addCandidate=t=>{if(!t||t.candidate===""){this.logger.debug("ice gathering is finished, force flush local candidates"),this.flushCandidates();return}this.logger.debug("onicecandidate",{candidate:t}),this.candidates.push(t),this.timeoutId?(clearTimeout(this.timeoutId),this.timeoutId=setTimeout(this.flushCandidates,this.delayMs)):this.timeoutId=setTimeout(this.flushCandidates,this.delayMs)};this.flushCandidates=()=>{this.candidates.length>0&&(this.onIceCandidates(this.candidates),this.candidates=[]),this.timeoutId=null};this.flush=()=>{this.timeoutId&&clearTimeout(this.timeoutId),this.flushCandidates()};this.close=()=>{this.timeoutId&&clearTimeout(this.timeoutId)};this.logger=t.sub("icebatcher"),this.delayMs=n,this.onIceCandidates=r}};import{RpcError as or}from"@protobuf-ts/runtime-rpc";import{GrpcStatusCode as S,GrpcWebFetchTransport as ar}from"@protobuf-ts/grpcweb-transport";import{jwtDecode as cr}from"jwt-decode";var pr="https://cloud.pulsebeam.dev/grpc";var rt=class{constructor(t,n,r,i){this.onsession=t=>{};this.onstatechange=()=>{};this.peerId=r.peerId,this.logger=t.sub("peer",{peerId:this.peerId}),this.sessions=[],this._state="new";let s={bundlePolicy:"balanced",iceTransportPolicy:r.forceRelay?"relay":"all",iceCandidatePoolSize:0,iceServers:r.iceServers};this.transport=new H(n,{enableDiscovery:!1,groupId:r.groupId,peerId:r.peerId,logger:this.logger,isRecoverable:i}),this.transport.onstream=a=>{let o=new X(a,s);this.sessions.push(o),this.onsession(o)},this.transport.onclosed=()=>{this.close()}}start(){if(this._state==="closed")throw new Error("peer is already closed");this.transport.listen()}async close(){this.sessions=[],await this.transport.close(),this.setState("closed")}connect(t,n,r){return this.transport.connect(t,n,r)}get state(){return this._state}setState(t){t!==this._state&&(this._state=t,this.onstatechange())}},dr=[S[S.PERMISSION_DENIED],S[S.INVALID_ARGUMENT],S[S.ABORTED],S[S.NOT_FOUND],S[S.UNAUTHENTICATED]];function bt(e){return e instanceof Error?e instanceof or?!dr.includes(e.code):!0:!1}async function Wr(e){let t=e.token,n=new ar({baseUrl:e.baseUrl||pr,sendJson:!1,format:"binary",jsonOptions:{emitDefaultValues:!0,enumAsInteger:!0,ignoreUnknownFields:!0},interceptors:[{interceptUnary(c,p,u,m){return m.meta||(m.meta={}),m.meta.Authorization=`Bearer ${t}`,c(p,u,m)}}]}),r=new J(n),i=await M(async()=>await r.prepare({}),{baseDelay:50,maxDelay:1e3,maxRetries:5,isRecoverable:bt});if(i===null)throw new Error("createPeer aborted");let s=[...e.iceServers||[]];for(let c of i.response.iceServers)s.push({urls:c.urls,username:c.username,credential:c.credential});let a=cr(t),o={...e,iceServers:s,groupId:a.gid,peerId:a.pid};return new rt(new W("pulsebeam",void 0,St),r,o,bt)}_.disableLog(!1);_.disableWarnings(!1);console.log("UA: ",navigator.userAgent);console.log("webrtc-adapter is enabled",JSON.stringify({shim:_.browserShim,version:_.browserDetails},null,2));export{rt as Peer,Wr as createPeer};
|
36
|
+
`)}var W=class e{constructor(t,n,r){this.name=t;n||(n={}),r||(r=rr),this.sink=r,this.obj={...n,name:t}}log(t,n,r){let i=r||{};t({ts:Date.now(),message:n,...this.obj,...i})}debug(t,n){this.log(this.sink.DEBUG,t,n)}info(t,n){this.log(this.sink.INFO,t,n)}warn(t,n){this.log(this.sink.WARN,t,n)}error(t,n){this.log(this.sink.ERROR,t,n)}sub(t,n){return n||(n={}),new e(this.name+"."+t,{...this.obj,...n},this.sink)}};var nr=1,vt=5e3;function ir(e){return{candidate:e.candidate,sdpMid:e.sdpMid,sdpMLineIndex:e.sdpMLineIndex,usernameFragment:e.password}}function sr(e){switch(e){case 1:return"offer";case 2:return"answer";case 3:return"pranswer";case 4:return"rollback";default:throw new Error(`unexpected kind: ${e}`)}}function Tt(e){switch(e){case"offer":return 1;case"answer":return 2;case"pranswer":return 3;case"rollback":return 4;default:throw new Error(`unexpected sdp type: ${e}`)}}var X=class{constructor(t,n){this.stream=t;this.ondatachannel=()=>{};this.onconnectionstatechange=()=>{};this.ontrack=()=>{};this.triggerIceRestart=()=>{if(!this.impolite)return;let t=performance.now()-this.lastIceRestart;if(t<vt){let n=vt-t,r=window.setTimeout(()=>{this.triggerIceRestart(),this.timers=this.timers.filter(i=>i===r)},n);return}if(this.pc.connectionState!=="connected"){if(this.iceRestartCount>=nr){this.close("detected sustained network failure");return}this.logger.debug("triggered ICE restart"),this.pc.restartIce(),this.generationCounter++,this.iceRestartCount++,this.lastIceRestart=performance.now()}};this.sendSignal=t=>{this.stream.send({payloadType:{oneofKind:"signal",signal:{...t,generationCounter:this.generationCounter}}},!0)};this.handleSignal=async t=>{if(t.generationCounter<this.generationCounter){this.logger.warn("detected staled generationCounter signals, ignoring");return}this.addCandidates(t);let n=t.data;if(t.generationCounter>this.generationCounter){if(this.logger.debug("detected new generationCounter",{otherGenerationCounter:t.generationCounter,generationCounter:this.generationCounter,msg:n}),n.oneofKind==="iceCandidate"){this.logger.warn("expecting an offer but got ice candidates during an ICE restart, adding to pending.",{msg:n});return}this.generationCounter=t.generationCounter}if(n.oneofKind!="sdp")return;let r=n.sdp;this.logger.debug("received a SDP signal",{sdpKind:r.kind});let i=r.kind===1&&(this.makingOffer||this.pc.signalingState!=="stable");if(this.impolite&&i){this.logger.debug("ignored offer");return}if(this.logger.debug("creating an answer"),await this.pc.setRemoteDescription({type:sr(r.kind),sdp:r.sdp}),r.kind===1){if(await this.pc.setLocalDescription(),!this.pc.localDescription){this.logger.error("unexpected null local description");return}this.sendSignal({data:{oneofKind:"sdp",sdp:{kind:Tt(this.pc.localDescription.type),sdp:this.pc.localDescription.sdp}}})}this.checkPendingCandidates()};this.checkPendingCandidates=()=>{if(!["stable","have-local-offer","have-remote-offer"].includes(this.pc.signalingState)||!this.pc.remoteDescription){this.logger.debug("wait for adding pending candidates",{signalingState:this.pc.signalingState,iceConnectionState:this.pc.iceConnectionState,connectionState:this.pc.connectionState,remoteDescription:this.pc.remoteDescription,pendingCandidates:this.pendingCandidates.length});return}for(let n of this.pendingCandidates)!n.candidate||n.candidate===""||(this.pc.addIceCandidate(n).catch(r=>{this.logger.warn("failed to add candidate, skipping.",{candidate:n,e:r})}),this.logger.debug(`added ice: ${n.candidate}`));this.pendingCandidates=[]};this.pc=new RTCPeerConnection(n),this.makingOffer=!1,this.pendingCandidates=[],this.stream.info.connId===this.stream.other.connId?this.impolite=this.stream.info.peerId>this.stream.other.peerId:this.impolite=this.stream.info.connId>this.stream.other.connId,this.abort=new AbortController,this.logger=t.logger.sub("session",{role:this.impolite?"impolite":"polite"}),this.generationCounter=0,this.iceRestartCount=0,this.lastIceRestart=0,this.timers=[],this._connectionState="new",this.iceBatcher=new tt(this.logger,100,s=>this.sendLocalIceCandidates(s)),t.onsignal=s=>this.handleSignal(s),t.onclosed=s=>this.close(s),this.pc.oniceconnectionstatechange=async()=>{let s=await this.pc.getStats(),a=[],o=[],d=[];s.forEach(c=>{c.type==="candidate-pair"?a.push(c):c.type==="local-candidate"?o.push(c):c.type==="remote-candidate"&&d.push(c)}),this.logger.debug("iceconnectionstate changed",{connectionstate:this.pc.connectionState,iceconnectionstate:this.pc.iceConnectionState,local:o,remote:d,pair:a,pending:this.pendingCandidates})};let r=performance.now();this.pc.onconnectionstatechange=s=>{switch(this.logger.debug("connectionstate changed",{connectionstate:this.pc.connectionState,iceconnectionstate:this.pc.iceConnectionState}),this.setConnectionState(this.pc.connectionState,s),this.pc.connectionState){case"connecting":r=performance.now();break;case"connected":{let a=performance.now()-r;this.logger.debug(`it took ${a}ms to connect`),this.iceRestartCount=0;break}case"disconnected":this.triggerIceRestart();break;case"failed":this.close("connection failed");break;case"closed":break}};let i=!0;this.pc.onnegotiationneeded=async()=>{if(i){if(!this.impolite){this.stream.send({payloadType:{oneofKind:"join",join:{}}},!0);return}i=!1}try{if(this.makingOffer=!0,this.logger.debug("creating an offer"),await this.pc.setLocalDescription(),!this.pc.localDescription)throw new Error("expect localDescription to be not empty");this.sendSignal({data:{oneofKind:"sdp",sdp:{kind:Tt(this.pc.localDescription.type),sdp:this.pc.localDescription.sdp}}})}catch(s){s instanceof Error&&this.logger.error("failed in negotiating",{err:s})}finally{this.makingOffer=!1}},this.pc.onicecandidate=({candidate:s})=>{this.iceBatcher.addCandidate(s)},this.pc.ondatachannel=(...s)=>{this.ondatachannel&&this.ondatachannel(...s)},this.pc.ontrack=(...s)=>{this.ontrack&&this.ontrack(...s)}}addTrack(...t){return this.pc.addTrack(...t)}removeTrack(...t){return this.pc.removeTrack(...t)}createDataChannel(...t){return this.pc.createDataChannel(...t)}get connectionState(){return this.pc.connectionState}get closeReason(){return this._closeReason}get other(){return{groupId:this.stream.other.groupId,peerId:this.stream.other.peerId,connId:this.stream.other.connId}}close(t){if(this.abort.signal.aborted)return;this.abort.abort(t);for(let r of this.timers)clearTimeout(r);this.timers=[],this.iceBatcher.close(),this.stream.close(),this._closeReason=t,this.pc.close();let n=new Event("connectionstatechange");this.setConnectionState("closed",n),this.logger.debug("session closed",{connectionState:this.connectionState})}sendLocalIceCandidates(t){let n=[];for(let r of t){let i={candidate:"",sdpMLineIndex:0,sdpMid:""};i.candidate=r.candidate,i.sdpMLineIndex=r.sdpMLineIndex??void 0,i.sdpMid=r.sdpMid??void 0,i.username=r.usernameFragment??void 0,n.push(i)}this.sendSignal({data:{oneofKind:"iceCandidateBatch",iceCandidateBatch:{candidates:n}}})}setConnectionState(t,n){t!==this._connectionState&&this.onconnectionstatechange&&this.onconnectionstatechange(n)}addCandidates(t){let n=[];if(t.data.oneofKind==="iceCandidate")n.push(t.data.iceCandidate);else if(t.data.oneofKind==="iceCandidateBatch")n.push(...t.data.iceCandidateBatch.candidates);else return;this.pendingCandidates.push(...n.map(r=>ir(r))),this.checkPendingCandidates()}},tt=class{constructor(t,n,r){this.candidates=[];this.timeoutId=null;this.addCandidate=t=>{if(!t||t.candidate===""){this.logger.debug("ice gathering is finished, force flush local candidates"),this.flushCandidates();return}this.logger.debug("onicecandidate",{candidate:t}),this.candidates.push(t),this.timeoutId?(clearTimeout(this.timeoutId),this.timeoutId=setTimeout(this.flushCandidates,this.delayMs)):this.timeoutId=setTimeout(this.flushCandidates,this.delayMs)};this.flushCandidates=()=>{this.candidates.length>0&&(this.onIceCandidates(this.candidates),this.candidates=[]),this.timeoutId=null};this.flush=()=>{this.timeoutId&&clearTimeout(this.timeoutId),this.flushCandidates()};this.close=()=>{this.timeoutId&&clearTimeout(this.timeoutId)};this.logger=t.sub("icebatcher"),this.delayMs=n,this.onIceCandidates=r}};import{RpcError as or}from"@protobuf-ts/runtime-rpc";import{GrpcStatusCode as S,GrpcWebFetchTransport as ar}from"@protobuf-ts/grpcweb-transport";import{jwtDecode as cr}from"jwt-decode";var pr="https://cloud.pulsebeam.dev/grpc";var rt=class{constructor(t,n,r,i){this.onsession=t=>{};this.onstatechange=()=>{};this.peerId=r.peerId,this.logger=t.sub("peer",{peerId:this.peerId}),this.sessions=[],this._state="new";let s={bundlePolicy:"balanced",iceTransportPolicy:r.forceRelay?"relay":"all",iceCandidatePoolSize:0,iceServers:r.iceServers};this.transport=new H(n,{enableDiscovery:!1,groupId:r.groupId,peerId:r.peerId,logger:this.logger,isRecoverable:i}),this.transport.onstream=a=>{let o=new X(a,s);this.sessions.push(o),this.onsession(o)},this.transport.onclosed=()=>{this.close()}}start(){if(this._state==="closed")throw new Error("peer is already closed");this.transport.listen()}async close(){this.sessions=[],await this.transport.close(),this.setState("closed")}connect(t,n,r){return this.transport.connect(t,n,r)}get state(){return this._state}setState(t){t!==this._state&&(this._state=t,this.onstatechange())}},dr=[S[S.PERMISSION_DENIED],S[S.INVALID_ARGUMENT],S[S.ABORTED],S[S.NOT_FOUND],S[S.UNAUTHENTICATED]];function bt(e){return e instanceof Error?e instanceof or?!dr.includes(e.code):!0:!1}async function Wr(e){let t=e.token,n=new ar({baseUrl:e.baseUrl||pr,sendJson:!1,format:"binary",jsonOptions:{emitDefaultValues:!0,enumAsInteger:!0,ignoreUnknownFields:!0},interceptors:[{interceptUnary(c,p,u,m){return m.meta||(m.meta={}),m.meta.Authorization=`Bearer ${t}`,c(p,u,m)}}]}),r=new J(n),i=await M(async()=>await r.prepare({}),{baseDelay:50,maxDelay:1e3,maxRetries:5,isRecoverable:bt});if(i===null)throw new Error("createPeer aborted");let s=[...e.iceServers||[]];for(let c of i.response.iceServers)s.push({urls:c.urls,username:c.username,credential:c.credential});let a=cr(t),o={...e,iceServers:s,groupId:a.gid,peerId:a.pid};return new rt(new W("pulsebeam",void 0,St),r,o,bt)}_.disableLog(!1);_.disableWarnings(!1);console.log("UA: ",navigator.userAgent);console.log("webrtc-adapter is enabled",JSON.stringify({shim:_.browserShim,version:_.browserDetails},null,2));export{rt as Peer,Wr as createPeer};
|
37
37
|
//# sourceMappingURL=index.js.map
|