Skip to content

Commit

Permalink
implement transports
Browse files Browse the repository at this point in the history
  • Loading branch information
murat-dogan committed Sep 17, 2023
1 parent 4843bab commit eb1db6a
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 43 deletions.
42 changes: 30 additions & 12 deletions polyfill/RTCDtlsTransport.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,47 @@
import RTCIceTransport from './RTCIceTransport.js';

export default class _RTCDtlsTransport extends EventTarget {
#pc = null;
#extraFunctions = null;
#iceTransport = null;
#state = null;

onerror = createEmptyFunction();
onstatechange = createEmptyFunction();
onerror = null;
onstatechange = null;

constructor() {
constructor({ pc, extraFunctions }) {
super();
this.#pc = pc;
this.#extraFunctions = extraFunctions;

this.#iceTransport = new RTCIceTransport({ pc, extraFunctions });

// forward peerConnection events
this.#pc.addEventListener('connectionstatechange', () => {
this.dispatchEvent(new Event('statechange'));
});

// forward events to properties
this.addEventListener('statechange', (e) => {
if (this.onstatechange) this.onstatechange(e);
});
}

get iceTransport() {
return this.#iceTransport;
}

get state() {
return this.#state;
// reduce state from new, connecting, connected, disconnected, failed, closed, unknown
// to RTCDtlsTRansport states new, connecting, connected, closed, failed
let state = this.#pc ? this.#pc.connectionState : 'new';
if (state === 'disconnected' || state === 'unknown') {
state = 'closed';
}
return state;
}

getRemoteCertificates() {
/** */
// TODO: implement
return new ArrayBuffer(0);
}
}

function createEmptyFunction() {
return () => {
/** */
};
}
62 changes: 46 additions & 16 deletions polyfill/RTCIceTransport.js
Original file line number Diff line number Diff line change
@@ -1,55 +1,85 @@
import RTCIceCandidate from './RTCIceCandidate.js';

export default class _RTCIceTransport extends EventTarget {
#pc = null;
#extraFunctions = null;
#component = null;
#gatheringState = null;
#role = null;
#state = null;

ongatheringstatechange = createEmptyFunction();
onselectedcandidatepairchange = createEmptyFunction();
onstatechange = createEmptyFunction();
ongatheringstatechange = null;
onselectedcandidatepairchange = null;
onstatechange = null;

constructor() {
constructor({ pc, extraFunctions }) {
super();
this.#pc = pc;
this.#extraFunctions = extraFunctions;

// forward peerConnection events
this.#pc.addEventListener('icegatheringstatechange', () => {
this.dispatchEvent(new Event('gatheringstatechange'));
});
this.#pc.addEventListener('iceconnectionstatechange', () => {
console.log('*********');
this.dispatchEvent(new Event('statechange'));
});

// forward events to properties
this.addEventListener('gatheringstatechange', (e) => {
if (this.ongatheringstatechange) this.ongatheringstatechange(e);
});
this.addEventListener('statechange', (e) => {
if (this.onstatechange) this.onstatechange(e);
});
}

get component() {
// TODO: expose component from pc
return this.#component;
}

get gatheringState() {
return this.#gatheringState;
return this.#pc ? this.#pc.iceGatheringState : 'new';
}

get role() {
// return controlled or controlling
return this.#role;
}

get state() {
return this.#state;
return this.#pc ? this.#pc.iceConnectionState : 'new';
}

getLocalCandidates() {
/** */
return this.#pc ? this.#extraFunctions.localCandidates() : [];
}

getLocalParameters() {
/** */
}

getRemoteCandidates() {
/** */
return this.#pc ? this.#extraFunctions.remoteCandidates() : [];
}

getRemoteParameters() {
/** */
}

getSelectedCandidatePair() {
/** */
let cp = this.#extraFunctions.selectedCandidatePair();
if (!cp) return null;
return {
local: new RTCIceCandidate({
candidate: cp.local.candidate,
sdpMid: cp.local.mid,
}),
remote: new RTCIceCandidate({
candidate: cp.remote.candidate,
sdpMid: cp.remote.mid,
}),
};
}
}

function createEmptyFunction() {
return () => {
/** */
};
}
27 changes: 26 additions & 1 deletion polyfill/RTCPeerConnection.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import RTCSessionDescription from './RTCSessionDescription.js';
import RTCDataChannel from './RTCDataChannel.js';
import RTCIceCandidate from './RTCIceCandidate.js';
import { RTCDataChannelEvent, RTCPeerConnectionIceEvent } from './Events.js';
import RTCSctpTransport from './RTCSctpTransport.js';
import DOMException from 'node-domexception';

export default class _RTCPeerConnection extends EventTarget {
Expand All @@ -14,6 +15,9 @@ export default class _RTCPeerConnection extends EventTarget {
#canTrickleIceCandidates;
#sctp;

#localCandidates = [];
#remoteCandidates = [];

onconnectionstatechange;
ondatachannel;
onicecandidate;
Expand All @@ -32,7 +36,6 @@ export default class _RTCPeerConnection extends EventTarget {
this.#localAnswer = createDeferredPromise();
this.#dataChannels = new Set();
this.#canTrickleIceCandidates = null;
this.#sctp = null;

const iceServers = init ? init.iceServers : [];

Expand Down Expand Up @@ -95,6 +98,7 @@ export default class _RTCPeerConnection extends EventTarget {
return;
}

this.#localCandidates.push(new RTCIceCandidate({ candidate, sdpMid }));
this.dispatchEvent(new RTCPeerConnectionIceEvent(new RTCIceCandidate({ candidate, sdpMid })));
});

Expand All @@ -117,6 +121,24 @@ export default class _RTCPeerConnection extends EventTarget {
this.addEventListener('icecandidate', (e) => {
if (this.onicecandidate) this.onicecandidate(e);
});

this.#sctp = new RTCSctpTransport({
pc: this,
extraFunctions: {
maxDataChannelId: () => {
return this.#peerConnection.maxDataChannelId();
},
localCandidates: () => {
return this.#localCandidates;
},
remoteCandidates: () => {
return this.#remoteCandidates;
},
selectedCandidatePair: () => {
return this.#peerConnection.getSelectedCandidatePair();
},
},
});
}

get canTrickleIceCandidates() {
Expand Down Expand Up @@ -176,6 +198,9 @@ export default class _RTCPeerConnection extends EventTarget {
throw new DOMException('Candidate invalid');
}

this.#remoteCandidates.push(
new RTCIceCandidate({ candidate: candidate.candidate, sdpMid: candidate.sdpMid || '0' }),
);
this.#peerConnection.addRemoteCandidate(candidate.candidate, candidate.sdpMid || '0');
}

Expand Down
48 changes: 34 additions & 14 deletions polyfill/RTCSctpTransport.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,54 @@
import RTCDtlsTransport from './RTCDtlsTransport.js';

export default class _RTCSctpTransport extends EventTarget {
#maxChannels = null;
#maxMessageSize = null;
#state = null;
#pc = null;
#extraFunctions = null;
#transport = null;

onstatechange = createEmptyFunction();
onstatechange = null;

constructor(init = {}) {
constructor({ pc, extraFunctions }) {
super();
this.#pc = pc;
this.#extraFunctions = extraFunctions;

this.#transport = new RTCDtlsTransport({ pc, extraFunctions });

// forward peerConnection events
this.#pc.addEventListener('connectionstatechange', () => {
this.dispatchEvent(new Event('statechange'));
});

// forward events to properties
this.addEventListener('statechange', (e) => {
if (this.onstatechange) this.onstatechange(e);
});
}

get maxChannels() {
return this.#maxChannels;
if (this.state !== 'connected') return null;
return this.#pc ? this.#extraFunctions.maxDataChannelId() : 0;
}

get maxMessageSize() {
return this.#maxMessageSize;
// Default from libdatachannel
// Change that after exposing pc.maxMessageSize
return 256 * 1024;
}

get state() {
return this.#state;
// reduce state from new, connecting, connected, disconnected, failed, closed, unknown
// to RTCSctpTransport states connecting, connected, closed
let state = this.#pc.connectionState;
if (state === 'new' || state === 'connecting') {
state = 'connecting';
} else if (state === 'disconnected' || state === 'failed' || state === 'closed' || state === 'unknown') {
state = 'closed';
}
return state;
}

get transport() {
return this.#transport;
}
}

function createEmptyFunction() {
return () => {
/** */
};
}

0 comments on commit eb1db6a

Please sign in to comment.