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 () {
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) {
case 'BLE':
this._ws = new WebSocket('wss://device-manager.scratch.mit.edu:20110/scratch/ble');
pathname = 'scratch/ble';
break;
case 'BT':
this._ws = new WebSocket('wss://device-manager.scratch.mit.edu:20110/scratch/bt');
pathname = 'scratch/bt';
break;
default:
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.onclose = this._onClose;
this._ws.onerror = this._onError;
} else {
throw new Error('Must set open, close, message and error handlers before calling open on the socket');
}
this._ws.onmessage = this._onMessage.bind(this);
};
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 () {