UNPKG

@libp2p/webrtc-peer

Version:
82 lines 3.23 kB
import { WebRTCPeer } from './peer.js'; import { WebRTCHandshake } from './handshake.js'; import randombytes from 'iso-random-stream/src/random.js'; import { toString as uint8ArrayToString } from 'uint8arrays/to-string'; import { pEvent } from 'p-event'; import delay from 'delay'; import { CustomEvent } from '@libp2p/interfaces/events'; import { logger } from '@libp2p/logger'; const log = logger('libp2p:webrtc-peer:initator'); const ICECOMPLETE_TIMEOUT = 1000; export class WebRTCInitiator extends WebRTCPeer { constructor(opts = {}) { super({ ...opts, logPrefix: 'initiator' }); this.handleDataChannelEvent({ channel: this.peerConnection.createDataChannel(opts.dataChannelLabel ?? uint8ArrayToString(randombytes(20), 'hex').slice(0, 7), opts.dataChannelInit) }); this.handshake = new WebRTCInitiatorHandshake({ log: this.log, peerConnection: this.peerConnection, wrtc: this.wrtc, offerOptions: opts.offerOptions }); this.handshake.addEventListener('signal', event => { this.dispatchEvent(new CustomEvent('signal', { detail: event.detail })); }); } handleSignal(signal) { this.handshake.handleSignal(signal).catch(err => { this.log('error handling signal %o %o', signal, err); }); } } class WebRTCInitiatorHandshake extends WebRTCHandshake { constructor(options) { super(options); this.options = options; this.status = 'idle'; this.peerConnection.addEventListener('icecandidate', (event) => { if (event.candidate == null) { return; } const signal = { type: 'candidate', candidate: { candidate: event.candidate.candidate, sdpMLineIndex: event.candidate.sdpMLineIndex, sdpMid: event.candidate.sdpMid } }; log.trace('create candidate', signal); this.dispatchEvent(new CustomEvent('signal', { detail: signal })); this.dispatchEvent(new CustomEvent('ice-candidate')); }); } async handleRenegotiate() { if (this.status === 'negotiating') { this.log('already negotiating, queueing'); return; } this.status = 'negotiating'; const offer = await this.peerConnection.createOffer(this.options.offerOptions); await this.peerConnection.setLocalDescription(offer); // wait for at least one candidate before sending the offer await pEvent(this, 'ice-candidate'); await delay(ICECOMPLETE_TIMEOUT); log.trace('renegotiate', this.peerConnection.localDescription); this.dispatchEvent(new CustomEvent('signal', { detail: this.peerConnection.localDescription ?? offer })); } async handleAnswer(signal) { log.trace('handle answer', signal); await this.peerConnection.setRemoteDescription(new this.wrtc.RTCSessionDescription(signal)); this.status = 'idle'; } } //# sourceMappingURL=initiator.js.map