Skip to content

Commit cd04bff

Browse files
authored
Websocket refactor (#7)
* blocking all messages now by default * reconnect working and much cleaner * overall much cleaner implementation * Adding support for resuming Sibelius sessions
1 parent d15d830 commit cd04bff

File tree

5 files changed

+288
-89
lines changed

5 files changed

+288
-89
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
sibelius-session.json
2+
13
# Logs
24
logs
35
*.log

DoricoRemote.js

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ class DoricoRemote extends WebSocketClient {
1010
}
1111

1212
onOpen() {
13-
this.sendHandshake();
13+
this._sendHandshake();
14+
15+
super.onOpen();
1416
}
1517

16-
sendHandshake() {
18+
_sendHandshake() {
1719
const message = {
1820
message: 'connect',
1921
clientName: this.appName,
@@ -24,10 +26,10 @@ class DoricoRemote extends WebSocketClient {
2426
message.sessionToken = this.sessionToken;
2527
}
2628

27-
this.sendMessage(message);
29+
this.send(message);
2830
}
2931

30-
onMessage(data) {
32+
_processHandshake(data) {
3133
if (data.message === 'sessiontoken' && data.sessionToken) {
3234
this.sessionToken = data.sessionToken;
3335
console.log(`Received sessiontoken: ${this.sessionToken} - completing handshake`);
@@ -37,32 +39,24 @@ class DoricoRemote extends WebSocketClient {
3739
sessionToken: this.sessionToken
3840
}
3941

40-
this.sendMessage(message);
42+
this.send(message);
4143
}
4244
else if (data.message === 'response' && data.code === 'kConnected') {
4345
console.log(`Handshake complete for ${this.appName}`);
4446
this.handshakeDone = true; // Handshake is now complete
45-
this.sendQueuedMessages(); // Now safe to send queued messages
46-
}
47-
48-
if (this.callbackAddress && this.callbackAddress.length > 0) {
49-
receive(this.callbackAddress, data)
47+
this._processQueue(); // Now safe to send queued messages
5048
}
5149
}
5250

53-
onClose(event) {
54-
if (event.code === 1000) {
55-
console.log('Connection closed cleanly - send a command to open a new connection');
56-
// this.sessionToken = null;
57-
// this.handshakeDone = false;
58-
} else {
59-
console.log('Connection lost, retrying...');
51+
onMessage(data) {
52+
if (!this.handshakeDone && data.message === 'sessiontoken') {
53+
this._processHandshake(data);
6054
}
61-
}
62-
63-
close() {
64-
if (this.socket?.readyState === WebSocket.OPEN) {
65-
this.socket.close(1000, 'Unload');
55+
56+
super.onMessage(data);
57+
58+
if (this.callbackAddress && this.callbackAddress.length > 0) {
59+
receive(this.callbackAddress, data)
6660
}
6761
}
6862
}

SibeliusConnect.js

Lines changed: 75 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
const WebSocketClient = require('./WebSocketClient.js')
1+
const fs = nativeRequire('fs');
2+
3+
const WebSocketClient = require('./WebSocketClient.js');
4+
5+
const SIB_SESSION_FILE = 'sibelius-session.json'
26

37
class SibeliusConnect extends WebSocketClient {
48
constructor({ appName = 'Sibelius Connect Remote', callbackAddress = '/SibeliusCallback', port = 1898, plugins = [] } = {}) {
@@ -10,53 +14,109 @@ class SibeliusConnect extends WebSocketClient {
1014
this.handshakeDone = false;
1115
}
1216

13-
onOpen() {
14-
this.sendHandshake();
17+
onOpen(resolve) {
18+
// reset the message queue so we don't send a bunch of queued commands
19+
// on reconnect, and because we need to send the handshake message first
20+
this.messageQueue = [];
21+
this._sendHandshake();
22+
23+
super.onOpen(resolve);
1524
}
1625

17-
sendHandshake() {
26+
_sendHandshake() {
1827
const message = {
1928
handshakeVersion: '1.0',
2029
clientName: this.appName,
2130
message: 'connect',
2231
};
2332

33+
const sessionData = loadJSON(SIB_SESSION_FILE, (e) => {
34+
console.log(`${SIB_SESSION_FILE} not found - starting new session`)
35+
});
36+
this.sessionToken = sessionData?.sessionToken;
37+
2438
if (this.sessionToken) {
2539
message.sessionToken = this.sessionToken;
2640
} else if (this.plugins.length > 0) {
2741
// We can't send a new list of plugins unless we're starting a new session
2842
message.plugins = this.plugins;
2943
}
3044

31-
this.sendMessage(message);
45+
this.send(message);
46+
47+
if (message.sessionToken) {
48+
// Sibelius doesn't send a response if reconnecting with a sessionToken,
49+
// so we will simulate receiving the sessionToken again
50+
this.onMessage({ data: JSON.stringify(sessionData) })
51+
}
3252
}
3353

34-
onMessage(data) {
54+
_processHandshake(data) {
55+
console.log(data)
3556
if (data.sessionToken) {
3657
this.sessionToken = data.sessionToken;
3758
console.log('Received sessionToken:', this.sessionToken);
38-
this.handshakeDone = true; // Handshake is now complete
39-
this.sendQueuedMessages(); // Now safe to send queued messages
59+
saveJSON(SIB_SESSION_FILE, data, (e) => console.log("unable to save sessionToken", e));
60+
this.handshakeDone = true;
61+
}
62+
else {
63+
console.error("Handshake failed");
64+
}
65+
}
66+
67+
onMessage(event) {
68+
const data = JSON.parse(event.data);
69+
70+
if (!this.handshakeDone && data.sessionToken) {
71+
this._processHandshake(data);
4072
}
4173

74+
super.onMessage(event);
75+
4276
if (this.callbackAddress && this.callbackAddress.length > 0) {
43-
receive(this.callbackAddress, data)
77+
receive(this.callbackAddress, data);
4478
}
4579
}
4680

4781
onClose(event) {
4882
if (event.code === 1000) {
49-
console.log('Connection closed cleanly - send a command to open a new connection');
83+
console.log('Connection closing cleanly - will attempt a fresh connection');
5084
this.sessionToken = null;
5185
this.handshakeDone = false;
52-
} else {
53-
console.log('Connection lost, retrying...');
86+
this.cleanupSocket();
87+
this.shouldReconnect = true;
88+
89+
this._removeSessionFile(`${__dirname}/${SIB_SESSION_FILE}`);
90+
}
91+
92+
super.onClose(event)
93+
}
94+
95+
_removeSessionFile(file) {
96+
if (!fs.existsSync(file)) {
97+
return;
5498
}
99+
fs.unlink(file, (error) => {
100+
if (error) {
101+
console.warn(`Error removing ${file}`, error);
102+
this.shouldReconnect = false;
103+
return;
104+
}
105+
106+
console.log(`Removed ${file}`);
107+
})
55108
}
56109

57-
close() {
58-
if (this.socket?.readyState === WebSocket.OPEN) {
59-
this.socket.close(1000, 'Unload');
110+
async send(message) {
111+
if (!this.socket) {
112+
await this.connect()
113+
}
114+
115+
try {
116+
super.send(message);
117+
}
118+
catch (e) {
119+
console.error('caught error', e)
60120
}
61121
}
62122
}

0 commit comments

Comments
 (0)