topazcube 0.1.11 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server.cjs +59 -50
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +3 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.js +59 -50
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
- package/src/server.ts +69 -57
package/dist/server.js
CHANGED
|
@@ -330,13 +330,22 @@ var TopazCubeServer = class {
|
|
|
330
330
|
};
|
|
331
331
|
_wss = null;
|
|
332
332
|
_exited = false;
|
|
333
|
+
log(...args) {
|
|
334
|
+
this.log(this.name + ":", ...args);
|
|
335
|
+
}
|
|
336
|
+
warn(...args) {
|
|
337
|
+
this.warn(this.name + ":", ...args);
|
|
338
|
+
}
|
|
339
|
+
error(...args) {
|
|
340
|
+
this.error(this.name + ":", ...args);
|
|
341
|
+
}
|
|
333
342
|
constructor({
|
|
334
343
|
name = "TopazCubeServer",
|
|
335
344
|
cycle = 100,
|
|
336
345
|
port = 8799,
|
|
337
346
|
useHttps = false,
|
|
338
347
|
key = "./cert/key.pem",
|
|
339
|
-
cert = "./cert/
|
|
348
|
+
cert = "./cert/cert.pem",
|
|
340
349
|
MongoUrl = "mongodb://localhost:27017",
|
|
341
350
|
database = "topazcube",
|
|
342
351
|
collection = "documents",
|
|
@@ -373,10 +382,10 @@ var TopazCubeServer = class {
|
|
|
373
382
|
}).listen(this.port);
|
|
374
383
|
this._wss = new WebSocketServer({ server: httpsServer });
|
|
375
384
|
httpsServer = null;
|
|
376
|
-
|
|
385
|
+
this.log(this.name + " running on HTTPS port " + this.port);
|
|
377
386
|
} else {
|
|
378
387
|
this._wss = new WebSocketServer({ port: this.port });
|
|
379
|
-
|
|
388
|
+
this.log(this.name + " running on port " + this.port);
|
|
380
389
|
}
|
|
381
390
|
this._wss.on("connection", (client) => {
|
|
382
391
|
this._onConnected(client);
|
|
@@ -402,13 +411,13 @@ var TopazCubeServer = class {
|
|
|
402
411
|
this._exitSignal("SIGINT");
|
|
403
412
|
return;
|
|
404
413
|
}
|
|
405
|
-
|
|
414
|
+
this.log(`Key pressed: ${key2}`);
|
|
406
415
|
if (key2 == "s") {
|
|
407
|
-
|
|
416
|
+
this.log("Saving all documents...");
|
|
408
417
|
this._saveAllDocuments();
|
|
409
418
|
}
|
|
410
419
|
if (key2 == "i") {
|
|
411
|
-
|
|
420
|
+
this.log(
|
|
412
421
|
`Server: ${this.name}, Clients: ${this.clients.length}, Documents: ${Object.keys(this.documents).length}`
|
|
413
422
|
);
|
|
414
423
|
}
|
|
@@ -531,7 +540,7 @@ var TopazCubeServer = class {
|
|
|
531
540
|
patchTime = t2 - t1;
|
|
532
541
|
this.stats.tPatch.push(patchTime);
|
|
533
542
|
if (this.allowFastPatch) {
|
|
534
|
-
|
|
543
|
+
this.log(`update ${this.update} dt:${dtms}ms RTC:${this.stats._sendRTCUpdate}bytes, tUpdate: ${updateTime}ms, tPatch: ${patchTime}ms`);
|
|
535
544
|
}
|
|
536
545
|
this.stats._sendRTCUpdate = 0;
|
|
537
546
|
}
|
|
@@ -573,7 +582,7 @@ var TopazCubeServer = class {
|
|
|
573
582
|
client.subscribed = {};
|
|
574
583
|
client.dataChannel = null;
|
|
575
584
|
client.peerConnection = null;
|
|
576
|
-
|
|
585
|
+
this.log("client connected", client.ID);
|
|
577
586
|
this.clients.push(client);
|
|
578
587
|
client.on("error", () => {
|
|
579
588
|
this._onError(client, arguments);
|
|
@@ -643,7 +652,7 @@ var TopazCubeServer = class {
|
|
|
643
652
|
}
|
|
644
653
|
}
|
|
645
654
|
_onError(client, args) {
|
|
646
|
-
|
|
655
|
+
this.error("onError:", args);
|
|
647
656
|
}
|
|
648
657
|
_onDisconnected(client) {
|
|
649
658
|
if (client.dataChannel) {
|
|
@@ -652,7 +661,7 @@ var TopazCubeServer = class {
|
|
|
652
661
|
if (client.peerConnection) {
|
|
653
662
|
client.peerConnection.close();
|
|
654
663
|
}
|
|
655
|
-
|
|
664
|
+
this.log("client disconnected");
|
|
656
665
|
let index = this.clients.indexOf(client);
|
|
657
666
|
if (index !== -1) {
|
|
658
667
|
this.clients.splice(index, 1);
|
|
@@ -669,7 +678,7 @@ var TopazCubeServer = class {
|
|
|
669
678
|
}
|
|
670
679
|
let t3 = Date.now();
|
|
671
680
|
if (data.length > 4096) {
|
|
672
|
-
|
|
681
|
+
this.log(`Big message ${dl} -> ${data.length} (${(100 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`);
|
|
673
682
|
}
|
|
674
683
|
this.stats.send += data.byteLength;
|
|
675
684
|
if (this.simulateLatency) {
|
|
@@ -680,7 +689,7 @@ var TopazCubeServer = class {
|
|
|
680
689
|
client.send(data);
|
|
681
690
|
}
|
|
682
691
|
} catch (e) {
|
|
683
|
-
|
|
692
|
+
this.error("Error sending message:", e, message);
|
|
684
693
|
}
|
|
685
694
|
}
|
|
686
695
|
async broadcast(message, clients = false) {
|
|
@@ -787,7 +796,7 @@ var TopazCubeServer = class {
|
|
|
787
796
|
}
|
|
788
797
|
}
|
|
789
798
|
}
|
|
790
|
-
|
|
799
|
+
this.log("--------------------------------------------------");
|
|
791
800
|
for (let key in hasChanges) {
|
|
792
801
|
if (hasChanges[key]) {
|
|
793
802
|
let size = parseInt("" + count["" + key]);
|
|
@@ -889,7 +898,7 @@ var TopazCubeServer = class {
|
|
|
889
898
|
fdata: changes
|
|
890
899
|
};
|
|
891
900
|
let t3 = Date.now();
|
|
892
|
-
|
|
901
|
+
this.log(`_sendPatches: ${name} encode_changes: ${t2 - t1}ms broadcast:${t3 - t2}ms`);
|
|
893
902
|
}
|
|
894
903
|
}
|
|
895
904
|
}
|
|
@@ -915,7 +924,7 @@ var TopazCubeServer = class {
|
|
|
915
924
|
/*= WEBRTC ===================================================================*/
|
|
916
925
|
/*
|
|
917
926
|
async _processOffer(client: ClientType, data: any): Promise<void> {
|
|
918
|
-
//
|
|
927
|
+
//this.log("RTC: Offer received", data);
|
|
919
928
|
const peerConnection = new wrtc.RTCPeerConnection({
|
|
920
929
|
iceServers: [
|
|
921
930
|
{ urls: 'stun:stun.l.google.com:19302' },
|
|
@@ -929,43 +938,43 @@ var TopazCubeServer = class {
|
|
|
929
938
|
|
|
930
939
|
peerConnection.onicecandidate = (event: any) => {
|
|
931
940
|
if (event.candidate) {
|
|
932
|
-
//
|
|
941
|
+
//this.log("RTC: ICE candidate generated", event.candidate.candidate.substring(0, 50) + "...");
|
|
933
942
|
this.send(client, {
|
|
934
943
|
c: 'rtc-candidate',
|
|
935
944
|
type: 'ice-candidate',
|
|
936
945
|
candidate: event.candidate, // .toJSON()
|
|
937
946
|
})
|
|
938
947
|
} else {
|
|
939
|
-
//
|
|
948
|
+
//this.log("RTC: ICE candidate gathering complete");
|
|
940
949
|
}
|
|
941
950
|
}
|
|
942
951
|
|
|
943
952
|
peerConnection.onconnectionstatechange = () => {
|
|
944
|
-
//
|
|
953
|
+
//this.log(`RTC: Connection state changed: ${peerConnection.connectionState}`);
|
|
945
954
|
if (peerConnection.connectionState === 'connected') {
|
|
946
955
|
client.webRTCConnected = true
|
|
947
|
-
|
|
956
|
+
this.log(`RTC: Connection established with client ${client.ID}`)
|
|
948
957
|
} else if (
|
|
949
958
|
peerConnection.connectionState === 'failed' ||
|
|
950
959
|
peerConnection.connectionState === 'disconnected' ||
|
|
951
960
|
peerConnection.connectionState === 'closed'
|
|
952
961
|
) {
|
|
953
962
|
client.webRTCConnected = false
|
|
954
|
-
|
|
963
|
+
this.log(`RTC: Connection failed or closed with client ${client.ID}`)
|
|
955
964
|
}
|
|
956
965
|
}
|
|
957
966
|
|
|
958
967
|
peerConnection.onicegatheringstatechange = () => {
|
|
959
|
-
//
|
|
968
|
+
//this.log(`RTC: ICE gathering state: ${peerConnection.iceGatheringState}`);
|
|
960
969
|
}
|
|
961
970
|
|
|
962
971
|
peerConnection.oniceconnectionstatechange = () => {
|
|
963
|
-
//
|
|
972
|
+
//this.log(`RTC: ICE connection state: ${peerConnection.iceConnectionState}`);
|
|
964
973
|
if (
|
|
965
974
|
peerConnection.iceConnectionState === 'connected' ||
|
|
966
975
|
peerConnection.iceConnectionState === 'completed'
|
|
967
976
|
) {
|
|
968
|
-
//
|
|
977
|
+
//this.log(`RTC: ICE connection established with client ${client.ID}`);
|
|
969
978
|
}
|
|
970
979
|
}
|
|
971
980
|
|
|
@@ -973,7 +982,7 @@ var TopazCubeServer = class {
|
|
|
973
982
|
await peerConnection.setRemoteDescription(
|
|
974
983
|
new wrtc.RTCSessionDescription(data)
|
|
975
984
|
)
|
|
976
|
-
//
|
|
985
|
+
//this.log("RTC: Remote description set successfully");
|
|
977
986
|
|
|
978
987
|
client.dataChannel = peerConnection.createDataChannel('serverchannel', {
|
|
979
988
|
ordered: true,
|
|
@@ -981,13 +990,13 @@ var TopazCubeServer = class {
|
|
|
981
990
|
})
|
|
982
991
|
|
|
983
992
|
client.dataChannel.onopen = () => {
|
|
984
|
-
//
|
|
993
|
+
//this.log(`RTC: Data channel opened for client ${client.ID}`);
|
|
985
994
|
// Try sending a test message
|
|
986
995
|
try {
|
|
987
996
|
const testData = { c: 'test', message: 'Hello WebRTC' }
|
|
988
997
|
this.sendRTC(client, testData)
|
|
989
998
|
} catch (e) {
|
|
990
|
-
|
|
999
|
+
this.error(
|
|
991
1000
|
`RTC: Error sending test message to client ${client.ID}`,
|
|
992
1001
|
e
|
|
993
1002
|
)
|
|
@@ -995,23 +1004,23 @@ var TopazCubeServer = class {
|
|
|
995
1004
|
}
|
|
996
1005
|
|
|
997
1006
|
client.dataChannel.onclose = () => {
|
|
998
|
-
|
|
1007
|
+
this.log(`RTC: Data channel closed for client ${client.ID}`)
|
|
999
1008
|
}
|
|
1000
1009
|
|
|
1001
1010
|
client.dataChannel.onerror = (error: Event) => {
|
|
1002
|
-
|
|
1011
|
+
this.error(`RTC: Data channel error for client ${client.ID}:`, error)
|
|
1003
1012
|
}
|
|
1004
1013
|
|
|
1005
1014
|
client.dataChannel.onmessage = (event: MessageEvent) => {
|
|
1006
1015
|
try {
|
|
1007
1016
|
const data = decode(event.data)
|
|
1008
|
-
|
|
1017
|
+
this.log(
|
|
1009
1018
|
`RTC: Data channel message from client ${client.ID}:`,
|
|
1010
1019
|
data
|
|
1011
1020
|
)
|
|
1012
1021
|
//this.onMessage(client, data);
|
|
1013
1022
|
} catch (error) {
|
|
1014
|
-
|
|
1023
|
+
this.error(
|
|
1015
1024
|
`RTC: Error decoding message from client ${client.ID}:`,
|
|
1016
1025
|
error
|
|
1017
1026
|
)
|
|
@@ -1022,14 +1031,14 @@ var TopazCubeServer = class {
|
|
|
1022
1031
|
const answer = await peerConnection.createAnswer()
|
|
1023
1032
|
await peerConnection.setLocalDescription(answer)
|
|
1024
1033
|
|
|
1025
|
-
//
|
|
1034
|
+
//this.log(`RTC: Sending answer to client ${client.ID}`);
|
|
1026
1035
|
this.send(client, {
|
|
1027
1036
|
c: 'rtc-answer',
|
|
1028
1037
|
type: answer.type,
|
|
1029
1038
|
sdp: answer.sdp,
|
|
1030
1039
|
})
|
|
1031
1040
|
} catch (error) {
|
|
1032
|
-
|
|
1041
|
+
this.error(
|
|
1033
1042
|
`RTC: Error processing offer from client ${client.ID}:`,
|
|
1034
1043
|
error
|
|
1035
1044
|
)
|
|
@@ -1037,19 +1046,19 @@ var TopazCubeServer = class {
|
|
|
1037
1046
|
}
|
|
1038
1047
|
|
|
1039
1048
|
async _processICECandidate(client: ClientType, data: any): Promise<void> {
|
|
1040
|
-
//
|
|
1049
|
+
//this.log(`RTC: Processing ICE candidate from client ${client.ID}`);
|
|
1041
1050
|
try {
|
|
1042
1051
|
if (client.peerConnection && data.candidate) {
|
|
1043
1052
|
await client.peerConnection.addIceCandidate(
|
|
1044
1053
|
data.candidate
|
|
1045
1054
|
//new wrtc.RTCIceCandidate(data.candidate)
|
|
1046
1055
|
)
|
|
1047
|
-
//
|
|
1056
|
+
//this.log(`RTC: ICE candidate added successfully for client ${client.ID}`);
|
|
1048
1057
|
} else {
|
|
1049
|
-
//
|
|
1058
|
+
//this.warn(`RTC: Cannot add ICE candidate for client ${client.ID} - peerConnection not ready or candidate missing`);
|
|
1050
1059
|
}
|
|
1051
1060
|
} catch (error) {
|
|
1052
|
-
|
|
1061
|
+
this.error(`RTC: Error adding ICE candidate for client ${client.ID}`)
|
|
1053
1062
|
}
|
|
1054
1063
|
}
|
|
1055
1064
|
|
|
@@ -1099,7 +1108,7 @@ var TopazCubeServer = class {
|
|
|
1099
1108
|
|
|
1100
1109
|
|
|
1101
1110
|
if (data.length > 16384) {
|
|
1102
|
-
|
|
1111
|
+
this.log(`BroadcastRTC message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)
|
|
1103
1112
|
}
|
|
1104
1113
|
|
|
1105
1114
|
let packages = this._splitRTCMessage(data)
|
|
@@ -1129,7 +1138,7 @@ var TopazCubeServer = class {
|
|
|
1129
1138
|
let packages: Uint8Array[]
|
|
1130
1139
|
if (data.byteLength > 65535) {
|
|
1131
1140
|
const now = Date.now()
|
|
1132
|
-
|
|
1141
|
+
this.warn(`RTC: Message too large: ${data.byteLength} bytes`)
|
|
1133
1142
|
// Split the message into smaller packages
|
|
1134
1143
|
packages = [];
|
|
1135
1144
|
let offset = 0;
|
|
@@ -1157,10 +1166,10 @@ var TopazCubeServer = class {
|
|
|
1157
1166
|
seq++;
|
|
1158
1167
|
}
|
|
1159
1168
|
|
|
1160
|
-
|
|
1169
|
+
this.log(`RTC: Large message split into ${packages.length} packages`);
|
|
1161
1170
|
} else {
|
|
1162
1171
|
packages = [data]
|
|
1163
|
-
|
|
1172
|
+
this.log(`RTC: Message - ${data.byteLength} bytes`)
|
|
1164
1173
|
}
|
|
1165
1174
|
return packages
|
|
1166
1175
|
}
|
|
@@ -1183,16 +1192,16 @@ var TopazCubeServer = class {
|
|
|
1183
1192
|
this.mongoClient = new MongoClient(this.MongoUrl);
|
|
1184
1193
|
try {
|
|
1185
1194
|
await this.mongoClient.connect();
|
|
1186
|
-
|
|
1195
|
+
this.log("Connected to MongoDB");
|
|
1187
1196
|
const db = this.mongoClient.db(this.database);
|
|
1188
1197
|
this.DB = db;
|
|
1189
1198
|
} catch (error) {
|
|
1190
|
-
|
|
1199
|
+
this.error("Error connecting to MongoDB:", error);
|
|
1191
1200
|
this.mongoClient = null;
|
|
1192
1201
|
}
|
|
1193
1202
|
}
|
|
1194
1203
|
async _loadDocument(name) {
|
|
1195
|
-
|
|
1204
|
+
this.log(`Loading document '${name}' from MongoDB`);
|
|
1196
1205
|
if (this.DB) {
|
|
1197
1206
|
try {
|
|
1198
1207
|
const doc = await this.DB.collection(this.collection).findOne({
|
|
@@ -1203,10 +1212,10 @@ var TopazCubeServer = class {
|
|
|
1203
1212
|
this.documents[name] = doc;
|
|
1204
1213
|
}
|
|
1205
1214
|
} catch (error) {
|
|
1206
|
-
|
|
1215
|
+
this.error("Error loading document from MongoDB:", error);
|
|
1207
1216
|
}
|
|
1208
1217
|
} else {
|
|
1209
|
-
|
|
1218
|
+
this.warn("MongoDB client not initialized. Document not loaded.");
|
|
1210
1219
|
}
|
|
1211
1220
|
}
|
|
1212
1221
|
async _saveDocument(name) {
|
|
@@ -1214,18 +1223,18 @@ var TopazCubeServer = class {
|
|
|
1214
1223
|
try {
|
|
1215
1224
|
const doc = this.documents[name];
|
|
1216
1225
|
let newdoc = clonewo_(doc, "__");
|
|
1217
|
-
|
|
1226
|
+
this.log(`Saving document '${name}' to MongoDB`);
|
|
1218
1227
|
await this.DB.collection(this.collection).updateOne(
|
|
1219
1228
|
{ name },
|
|
1220
1229
|
{ $set: newdoc },
|
|
1221
1230
|
{ upsert: true }
|
|
1222
1231
|
);
|
|
1223
|
-
|
|
1232
|
+
this.log("Document saved to MongoDB");
|
|
1224
1233
|
} catch (error) {
|
|
1225
|
-
|
|
1234
|
+
this.error("Error saving document to MongoDB:", error);
|
|
1226
1235
|
}
|
|
1227
1236
|
} else {
|
|
1228
|
-
|
|
1237
|
+
this.warn("MongoDB client not initialized. Document not saved.");
|
|
1229
1238
|
}
|
|
1230
1239
|
}
|
|
1231
1240
|
async _saveAllDocuments() {
|
|
@@ -1244,7 +1253,7 @@ var TopazCubeServer = class {
|
|
|
1244
1253
|
/*= EXIT ===================================================================*/
|
|
1245
1254
|
_exitSignal(signal) {
|
|
1246
1255
|
if (!this._exited) {
|
|
1247
|
-
|
|
1256
|
+
this.log("\nEXIT: Caught interrupt signal " + signal);
|
|
1248
1257
|
this._exited = true;
|
|
1249
1258
|
clearInterval(this._loopiv);
|
|
1250
1259
|
this.onBeforeExit();
|