Merge pull request #3510 from cwillisf/scratch-link-ws

support Scratch Link on ws://127.0.0.1:20111
This commit is contained in:
Christopher Willis-Ford 2022-02-18 13:19:39 -08:00 committed by GitHub
commit 5ff017cbe2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -23,26 +23,75 @@ class ScratchLinkWebSocket {
} }
open () { open () {
if (!(this._onOpen && this._onClose && this._onError && this._handleMessage)) {
throw new Error('Must set open, close, message and error handlers before calling open on the socket');
}
let pathname;
switch (this._type) { switch (this._type) {
case 'BLE': case 'BLE':
this._ws = new WebSocket('wss://device-manager.scratch.mit.edu:20110/scratch/ble'); pathname = 'scratch/ble';
break; break;
case 'BT': case 'BT':
this._ws = new WebSocket('wss://device-manager.scratch.mit.edu:20110/scratch/bt'); pathname = 'scratch/bt';
break; break;
default: default:
throw new Error(`Unknown ScratchLink socket Type: ${this._type}`); throw new Error(`Unknown ScratchLink socket Type: ${this._type}`);
} }
if (this._onOpen && this._onClose && this._onError && this._handleMessage) { // Try ws:// (the new way) and wss:// (the old way) simultaneously. If either connects, close the other. If we
// were to try one and fall back to the other on failure, that could mean a delay of 30 seconds or more for
// those who need the fallback.
// If both connections fail we should report only one error.
const setSocket = (socketToUse, socketToClose) => {
socketToClose.onopen = socketToClose.onerror = null;
socketToClose.close();
this._ws = socketToUse;
this._ws.onopen = this._onOpen; this._ws.onopen = this._onOpen;
this._ws.onclose = this._onClose; this._ws.onclose = this._onClose;
this._ws.onerror = this._onError; this._ws.onerror = this._onError;
} else { this._ws.onmessage = this._onMessage.bind(this);
throw new Error('Must set open, close, message and error handlers before calling open on the socket'); };
}
this._ws.onmessage = this._onMessage.bind(this); const ws = new WebSocket(`ws://127.0.0.1:20111/${pathname}`);
const wss = new WebSocket(`wss://device-manager.scratch.mit.edu:20110/${pathname}`);
const connectTimeout = setTimeout(() => {
// neither socket succeeded before the timeout
setSocket(ws, wss);
this._ws.onerror(new Event('timeout'));
}, 15 * 1000);
ws.onopen = openEvent => {
clearTimeout(connectTimeout);
setSocket(ws, wss);
this._ws.onopen(openEvent);
};
wss.onopen = openEvent => {
clearTimeout(connectTimeout);
setSocket(wss, ws);
this._ws.onopen(openEvent);
};
let wsError;
let wssError;
const errorHandler = () => {
// if only one has received an error, we haven't overall failed yet
if (wsError && wssError) {
clearTimeout(connectTimeout);
setSocket(ws, wss);
this._ws.onerror(wsError);
}
};
ws.onerror = errorEvent => {
wsError = errorEvent;
errorHandler();
};
wss.onerror = errorEvent => {
wssError = errorEvent;
errorHandler();
};
} }
close () { close () {