This is an automated email from the git hooks/post-receive script.
meskio pushed a commit to branch main in repository pluggable-transports/snowflake-webext.
commit 17168c1f57c177e74ade038d1394476b2c740e3c Author: WofWca wofwca@protonmail.com AuthorDate: Sat Jun 18 18:23:12 2022 +0300
refactor: convert some comments to JSDoc, improve types --- broker.js | 36 +++++++++++++++++++------------ proxypair.js | 25 +++++++++++----------- snowflake.js | 31 +++++++++++++++++---------- ui.js | 2 +- util.js | 70 +++++++++++++++++++++++++++++++++++++----------------------- websocket.js | 6 ++++-- 6 files changed, 102 insertions(+), 68 deletions(-)
diff --git a/broker.js b/broker.js index 8d084e0..128eda7 100644 --- a/broker.js +++ b/broker.js @@ -1,6 +1,6 @@ /* global log, dbg, snowflake */
-/* +/** Communication with the snowflake broker.
Browser snowflakes must register with the broker in order @@ -10,10 +10,12 @@ to get assigned to clients. // Represents a broker running remotely. class Broker {
- // When interacting with the Broker, snowflake must generate a unique session - // ID so the Broker can keep track of each proxy's signalling channels. - // On construction, this Broker object does not do anything until - // |getClientOffer| is called. + /** + * When interacting with the Broker, snowflake must generate a unique session + * ID so the Broker can keep track of each proxy's signalling channels. + * On construction, this Broker object does not do anything until + * `getClientOffer` is called. + */ constructor(config) { this.getClientOffer = this.getClientOffer.bind(this); this._postRequest = this._postRequest.bind(this); @@ -34,11 +36,13 @@ class Broker { } }
- // Promises some client SDP Offer. - // Registers this Snowflake with the broker using an HTTP POST request, and - // waits for a response containing some client offer that the Broker chooses - // for this proxy.. - // TODO: Actually support multiple clients. + /** + * Promises some client SDP Offer. + * Registers this Snowflake with the broker using an HTTP POST request, and + * waits for a response containing some client offer that the Broker chooses + * for this proxy.. + * TODO: Actually support multiple clients. + */ getClientOffer(id, numClientsConnected) { return new Promise((fulfill, reject) => { const xhr = new XMLHttpRequest(); @@ -77,8 +81,10 @@ class Broker { }); }
- // Assumes getClientOffer happened, and a WebRTC SDP answer has been generated. - // Sends it back to the broker, which passes it to back to the original client. + /** + * Assumes getClientOffer happened, and a WebRTC SDP answer has been generated. + * Sends it back to the broker, which passes it to back to the original client. + */ sendAnswer(id, answer) { dbg(id + ' - Sending answer back to broker...\n'); dbg(answer.sdp); @@ -104,8 +110,10 @@ class Broker { this.natType = natType; }
- // urlSuffix for the broker is different depending on what action - // is desired. + /** + * urlSuffix for the broker is different depending on what action + * is desired. + */ _postRequest(xhr, urlSuffix, payload) { try { xhr.open('POST', this.url + urlSuffix); diff --git a/proxypair.js b/proxypair.js index e423b59..880f202 100644 --- a/proxypair.js +++ b/proxypair.js @@ -1,6 +1,6 @@ /* global snowflake, log, dbg, Util, Parse, WS */
-/* +/** Represents a single:
client <-- webrtc --> snowflake <-- websocket --> relay @@ -11,11 +11,10 @@ Broker with an WebRTC answer.
class ProxyPair {
- /* - Constructs a ProxyPair where: - - @relayAddr is the destination relay - - @rateLimit specifies a rate limit on traffic - */ + /** + * @param relayAddr the destination relay + * @param {*} rateLimit specifies a rate limit on traffic + */ constructor(relayAddr, rateLimit, config) { this.prepareDataChannel = this.prepareDataChannel.bind(this); this.connectRelay = this.connectRelay.bind(this); @@ -35,7 +34,7 @@ class ProxyPair { this.counted = false; }
- // Prepare a WebRTC PeerConnection and await for an SDP offer. + /** Prepare a WebRTC PeerConnection and await for an SDP offer. */ begin() { this.pc = new RTCPeerConnection(this.pcConfig); this.pc.onicecandidate = (evt) => { @@ -69,7 +68,7 @@ class ProxyPair { return true; }
- // Given a WebRTC DataChannel, prepare callbacks. + /** Given a WebRTC DataChannel, prepare callbacks. */ prepareDataChannel(channel) { channel.onopen = () => { log('WebRTC DataChannel opened!'); @@ -96,7 +95,7 @@ class ProxyPair { return channel.onmessage = this.onClientToRelayMessage; }
- // Assumes WebRTC datachannel is connected. + /** Assumes WebRTC datachannel is connected. */ connectRelay() { dbg('Connecting to relay...'); // Get a remote IP address from the PeerConnection, if possible. Add it to @@ -147,7 +146,7 @@ class ProxyPair { }), 5000); }
- // WebRTC --> websocket + /** WebRTC --> websocket */ onClientToRelayMessage(msg) { if (this.messageTimer) { clearTimeout(this.messageTimer); @@ -165,7 +164,7 @@ class ProxyPair { return this.flush(); }
- // websocket --> WebRTC + /** websocket --> WebRTC */ onRelayToClientMessage(event) { dbg('websocket --> WebRTC data: ' + event.data.byteLength + ' bytes'); this.r2cSchedule.push(event.data); @@ -178,7 +177,7 @@ class ProxyPair { return this.close(); }
- // Close both WebRTC and websocket. + /** Close both WebRTC and websocket. */ close() { if (this.timer) { clearTimeout(this.timer); @@ -200,7 +199,7 @@ class ProxyPair { this.onCleanup(); }
- // Send as much data in both directions as the rate limit currently allows. + /** Send as much data in both directions as the rate limit currently allows. */ flush() { if (this.flush_timeout_id) { clearTimeout(this.flush_timeout_id); diff --git a/snowflake.js b/snowflake.js index 7354b97..2c94cf8 100644 --- a/snowflake.js +++ b/snowflake.js @@ -1,6 +1,6 @@ /* global log, dbg, DummyRateLimit, BucketRateLimit, ProxyPair */
-/* +/** A JavaScript WebRTC snowflake proxy
Uses WebRTC from the client, and Websocket to the server. @@ -32,16 +32,20 @@ class Snowflake { this.retries = 0; }
- // Set the target relay address spec, which is expected to be websocket. - // TODO: Should potentially fetch the target from broker later, or modify - // entirely for the Tor-independent version. + /** + * Set the target relay address spec, which is expected to be websocket. + * TODO: Should potentially fetch the target from broker later, or modify + * entirely for the Tor-independent version. + */ setRelayAddr(relayAddr) { this.relayAddr = relayAddr; log('Using ' + relayAddr.host + ':' + relayAddr.port + ' as Relay.'); }
- // Initialize WebRTC PeerConnection, which requires beginning the signalling - // process. |pollBroker| automatically arranges signalling. + /** + * Initialize WebRTC PeerConnection, which requires beginning the signalling + * process. `pollBroker` automatically arranges signalling. + */ beginWebRTC() { this.pollBroker(); this.pollTimeoutId = setTimeout((() => { @@ -49,8 +53,10 @@ class Snowflake { }), this.pollInterval); }
- // Regularly poll Broker for clients to serve until this snowflake is - // serving at capacity, at which point stop polling. + /** + * Regularly poll Broker for clients to serve until this snowflake is + * serving at capacity, at which point stop polling. + */ pollBroker() { // Poll broker for clients. const pair = this.makeProxyPair(); @@ -110,8 +116,11 @@ class Snowflake { this.retries++; }
- // Receive an SDP offer from some client assigned by the Broker, - // |pair| - an available ProxyPair. + /** + * Receive an SDP offer from some client assigned by the Broker + * @param {ProxyPair} pair an available ProxyPair. + * @returns {boolean} `true` on success, `false` on fail. + */ receiveOffer(pair, desc, relayURL) { try { if (relayURL !== undefined) { @@ -180,7 +189,7 @@ class Snowflake { return pair; }
- // Stop all proxypairs. + /** Stop all proxypairs. */ disable() { log('Disabling Snowflake.'); clearTimeout(this.pollTimeoutId); diff --git a/ui.js b/ui.js index de8670d..6358758 100644 --- a/ui.js +++ b/ui.js @@ -1,4 +1,4 @@ -/* +/** All of Snowflake's DOM manipulation and inputs. */
diff --git a/util.js b/util.js index 9a7673b..bf73571 100644 --- a/util.js +++ b/util.js @@ -1,7 +1,7 @@ /* exported Util, Params, DummyRateLimit */ /* global Config */
-/* +/** A JavaScript WebRTC snowflake proxy
Contains helpers for parsing query strings and other utilities. @@ -21,10 +21,12 @@ class Util { return navigator.cookieEnabled; }
- // returns a promise that resolves to "restricted" if we - // fail to make a test connection to a known restricted - // NAT, "unrestricted" if the test connection succeeds, and - // "unknown" if we fail to reach the probe test server + /** + * returns a promise that resolves to "restricted" if we + * fail to make a test connection to a known restricted + * NAT, "unrestricted" if the test connection succeeds, and + * "unknown" if we fail to reach the probe test server + */ static checkNATType(timeout) { let pc = new RTCPeerConnection({iceServers: [ {urls: 'stun:stun1.l.google.com:19302'} @@ -65,8 +67,10 @@ class Util { })); }
- // Assumes getClientOffer happened, and a WebRTC SDP answer has been generated. - // Sends it back to the broker, which passes it back to the original client. + /** + * Assumes getClientOffer happened, and a WebRTC SDP answer has been generated. + * Sends it back to the broker, which passes it back to the original client. + */ static sendOffer(offer) { return new Promise((fulfill, reject) => { const xhr = new XMLHttpRequest(); @@ -99,9 +103,11 @@ class Util {
class Parse {
- // Parse a cookie data string (usually document.cookie). The return type is an - // object mapping cookies names to values. Returns null on error. - // http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-8747038 + /** + * Parse a cookie data string (usually document.cookie). The return type is an + * object mapping cookies names to values. Returns null on error. + * http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-8747038 + */ static cookie(cookies) { const result = {}; const strings = cookies ? cookies.split(';') : []; @@ -120,8 +126,10 @@ class Parse { return result; }
- // Parse an address in the form 'host:port'. Returns an Object with keys 'host' - // (String) and 'port' (int). Returns null on error. + /** + * Parse an address in the form 'host:port'. Returns an Object with keys 'host' + * (String) and 'port' (int). Returns null on error. + */ static address(spec) { let m = null; if (!m) { @@ -147,8 +155,10 @@ class Parse { }; }
- // Parse a count of bytes. A suffix of 'k', 'm', or 'g' (or uppercase) - // does what you would think. Returns null on error. + /** + * Parse a count of bytes. A suffix of 'k', 'm', or 'g' (or uppercase) + * does what you would think. Returns null on error. + */ static byteCount(spec) { let matches = spec.match(/^(\d+(?:.\d*)?)(\w*)$/); if (matches === null) { @@ -172,11 +182,13 @@ class Parse { return count * multiplier; }
- //Parse a remote connection-address out of the "c=" Connection Data field - // or the "a=" attribute fields of the session description. - // Return undefined if none is found. - // https://tools.ietf.org/html/rfc4566#section-5.7 - // https://tools.ietf.org/html/rfc5245#section-15 + /** + * Parse a remote connection-address out of the "c=" Connection Data field + * or the "a=" attribute fields of the session description. + * Return undefined if none is found. + * https://tools.ietf.org/html/rfc4566#section-5.7 + * https://tools.ietf.org/html/rfc5245#section-15 + */ static ipFromSDP(sdp) { console.log(sdp); const ref = [ @@ -195,8 +207,10 @@ class Parse { } }
- // Parse the mapped port out of an ice candidate returned from the - // onicecandidate callback + /** + * Parse the mapped port out of an ice candidate returned from the + * onicecandidate callback + */ static portFromCandidate(c) { const pattern = /(?:[\d.]+|[0-9A-Fa-f:.]+) (\d+) typ srflx/m; const m = pattern.exec(c); @@ -206,7 +220,7 @@ class Parse { return null; }
- // Determine whether an IP address is a local, unspecified, or loopback address + /** Determine whether an IP address is a local, unspecified, or loopback address */ static isRemoteIP(ip) { if (ip.includes(":")) { var ip6 = ip.split(':'); @@ -249,9 +263,11 @@ class Params { return null; }
- // Get an object value and parse it as a byte count. Example byte counts are - // '100' and '1.3m'. Returns |defaultValue| if param is not a key. Return null - // on a parsing error. + /** + * Get an object value and parse it as a byte count. Example byte counts are + * '100' and '1.3m'. Returns |defaultValue| if param is not a key. Return null + * on a parsing error. + */ static getByteCount(query, param, defaultValue) { if (!query.has(param)) { return defaultValue; @@ -285,7 +301,7 @@ class BucketRateLimit { return this.amount <= this.capacity; }
- // How many seconds in the future will the limit expire? + /** How many seconds in the future will the limit expire? */ when() { this.age(); return (this.amount - this.capacity) / (this.capacity / this.time); @@ -303,7 +319,7 @@ BucketRateLimit.prototype.amount = 0.0; BucketRateLimit.prototype.lastUpdate = new Date();
-// A rate limiter that never limits. +/** A rate limiter that never limits. */ class DummyRateLimit {
constructor(capacity, time) { diff --git a/websocket.js b/websocket.js index fdf470c..b2d509a 100644 --- a/websocket.js +++ b/websocket.js @@ -4,8 +4,10 @@ Only websocket-specific stuff.
class WS {
- // Build an escaped URL string from unescaped components. Only scheme and host - // are required. See RFC 3986, section 3. + /** + * Build an escaped URL string from unescaped components. Only scheme and host + * are required. See RFC 3986, section 3. + */ static buildUrl(scheme, host, port, path, params) { var parts; parts = [];