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.cjs
CHANGED
|
@@ -364,13 +364,22 @@ var TopazCubeServer = class {
|
|
|
364
364
|
};
|
|
365
365
|
_wss = null;
|
|
366
366
|
_exited = false;
|
|
367
|
+
log(...args) {
|
|
368
|
+
this.log(this.name + ":", ...args);
|
|
369
|
+
}
|
|
370
|
+
warn(...args) {
|
|
371
|
+
this.warn(this.name + ":", ...args);
|
|
372
|
+
}
|
|
373
|
+
error(...args) {
|
|
374
|
+
this.error(this.name + ":", ...args);
|
|
375
|
+
}
|
|
367
376
|
constructor({
|
|
368
377
|
name = "TopazCubeServer",
|
|
369
378
|
cycle = 100,
|
|
370
379
|
port = 8799,
|
|
371
380
|
useHttps = false,
|
|
372
381
|
key = "./cert/key.pem",
|
|
373
|
-
cert = "./cert/
|
|
382
|
+
cert = "./cert/cert.pem",
|
|
374
383
|
MongoUrl = "mongodb://localhost:27017",
|
|
375
384
|
database = "topazcube",
|
|
376
385
|
collection = "documents",
|
|
@@ -407,10 +416,10 @@ var TopazCubeServer = class {
|
|
|
407
416
|
}).listen(this.port);
|
|
408
417
|
this._wss = new import_ws.WebSocketServer({ server: httpsServer });
|
|
409
418
|
httpsServer = null;
|
|
410
|
-
|
|
419
|
+
this.log(this.name + " running on HTTPS port " + this.port);
|
|
411
420
|
} else {
|
|
412
421
|
this._wss = new import_ws.WebSocketServer({ port: this.port });
|
|
413
|
-
|
|
422
|
+
this.log(this.name + " running on port " + this.port);
|
|
414
423
|
}
|
|
415
424
|
this._wss.on("connection", (client) => {
|
|
416
425
|
this._onConnected(client);
|
|
@@ -436,13 +445,13 @@ var TopazCubeServer = class {
|
|
|
436
445
|
this._exitSignal("SIGINT");
|
|
437
446
|
return;
|
|
438
447
|
}
|
|
439
|
-
|
|
448
|
+
this.log(`Key pressed: ${key2}`);
|
|
440
449
|
if (key2 == "s") {
|
|
441
|
-
|
|
450
|
+
this.log("Saving all documents...");
|
|
442
451
|
this._saveAllDocuments();
|
|
443
452
|
}
|
|
444
453
|
if (key2 == "i") {
|
|
445
|
-
|
|
454
|
+
this.log(
|
|
446
455
|
`Server: ${this.name}, Clients: ${this.clients.length}, Documents: ${Object.keys(this.documents).length}`
|
|
447
456
|
);
|
|
448
457
|
}
|
|
@@ -565,7 +574,7 @@ var TopazCubeServer = class {
|
|
|
565
574
|
patchTime = t2 - t1;
|
|
566
575
|
this.stats.tPatch.push(patchTime);
|
|
567
576
|
if (this.allowFastPatch) {
|
|
568
|
-
|
|
577
|
+
this.log(`update ${this.update} dt:${dtms}ms RTC:${this.stats._sendRTCUpdate}bytes, tUpdate: ${updateTime}ms, tPatch: ${patchTime}ms`);
|
|
569
578
|
}
|
|
570
579
|
this.stats._sendRTCUpdate = 0;
|
|
571
580
|
}
|
|
@@ -607,7 +616,7 @@ var TopazCubeServer = class {
|
|
|
607
616
|
client.subscribed = {};
|
|
608
617
|
client.dataChannel = null;
|
|
609
618
|
client.peerConnection = null;
|
|
610
|
-
|
|
619
|
+
this.log("client connected", client.ID);
|
|
611
620
|
this.clients.push(client);
|
|
612
621
|
client.on("error", () => {
|
|
613
622
|
this._onError(client, arguments);
|
|
@@ -677,7 +686,7 @@ var TopazCubeServer = class {
|
|
|
677
686
|
}
|
|
678
687
|
}
|
|
679
688
|
_onError(client, args) {
|
|
680
|
-
|
|
689
|
+
this.error("onError:", args);
|
|
681
690
|
}
|
|
682
691
|
_onDisconnected(client) {
|
|
683
692
|
if (client.dataChannel) {
|
|
@@ -686,7 +695,7 @@ var TopazCubeServer = class {
|
|
|
686
695
|
if (client.peerConnection) {
|
|
687
696
|
client.peerConnection.close();
|
|
688
697
|
}
|
|
689
|
-
|
|
698
|
+
this.log("client disconnected");
|
|
690
699
|
let index = this.clients.indexOf(client);
|
|
691
700
|
if (index !== -1) {
|
|
692
701
|
this.clients.splice(index, 1);
|
|
@@ -703,7 +712,7 @@ var TopazCubeServer = class {
|
|
|
703
712
|
}
|
|
704
713
|
let t3 = Date.now();
|
|
705
714
|
if (data.length > 4096) {
|
|
706
|
-
|
|
715
|
+
this.log(`Big message ${dl} -> ${data.length} (${(100 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`);
|
|
707
716
|
}
|
|
708
717
|
this.stats.send += data.byteLength;
|
|
709
718
|
if (this.simulateLatency) {
|
|
@@ -714,7 +723,7 @@ var TopazCubeServer = class {
|
|
|
714
723
|
client.send(data);
|
|
715
724
|
}
|
|
716
725
|
} catch (e) {
|
|
717
|
-
|
|
726
|
+
this.error("Error sending message:", e, message);
|
|
718
727
|
}
|
|
719
728
|
}
|
|
720
729
|
async broadcast(message, clients = false) {
|
|
@@ -821,7 +830,7 @@ var TopazCubeServer = class {
|
|
|
821
830
|
}
|
|
822
831
|
}
|
|
823
832
|
}
|
|
824
|
-
|
|
833
|
+
this.log("--------------------------------------------------");
|
|
825
834
|
for (let key in hasChanges) {
|
|
826
835
|
if (hasChanges[key]) {
|
|
827
836
|
let size = parseInt("" + count["" + key]);
|
|
@@ -923,7 +932,7 @@ var TopazCubeServer = class {
|
|
|
923
932
|
fdata: changes
|
|
924
933
|
};
|
|
925
934
|
let t3 = Date.now();
|
|
926
|
-
|
|
935
|
+
this.log(`_sendPatches: ${name} encode_changes: ${t2 - t1}ms broadcast:${t3 - t2}ms`);
|
|
927
936
|
}
|
|
928
937
|
}
|
|
929
938
|
}
|
|
@@ -949,7 +958,7 @@ var TopazCubeServer = class {
|
|
|
949
958
|
/*= WEBRTC ===================================================================*/
|
|
950
959
|
/*
|
|
951
960
|
async _processOffer(client: ClientType, data: any): Promise<void> {
|
|
952
|
-
//
|
|
961
|
+
//this.log("RTC: Offer received", data);
|
|
953
962
|
const peerConnection = new wrtc.RTCPeerConnection({
|
|
954
963
|
iceServers: [
|
|
955
964
|
{ urls: 'stun:stun.l.google.com:19302' },
|
|
@@ -963,43 +972,43 @@ var TopazCubeServer = class {
|
|
|
963
972
|
|
|
964
973
|
peerConnection.onicecandidate = (event: any) => {
|
|
965
974
|
if (event.candidate) {
|
|
966
|
-
//
|
|
975
|
+
//this.log("RTC: ICE candidate generated", event.candidate.candidate.substring(0, 50) + "...");
|
|
967
976
|
this.send(client, {
|
|
968
977
|
c: 'rtc-candidate',
|
|
969
978
|
type: 'ice-candidate',
|
|
970
979
|
candidate: event.candidate, // .toJSON()
|
|
971
980
|
})
|
|
972
981
|
} else {
|
|
973
|
-
//
|
|
982
|
+
//this.log("RTC: ICE candidate gathering complete");
|
|
974
983
|
}
|
|
975
984
|
}
|
|
976
985
|
|
|
977
986
|
peerConnection.onconnectionstatechange = () => {
|
|
978
|
-
//
|
|
987
|
+
//this.log(`RTC: Connection state changed: ${peerConnection.connectionState}`);
|
|
979
988
|
if (peerConnection.connectionState === 'connected') {
|
|
980
989
|
client.webRTCConnected = true
|
|
981
|
-
|
|
990
|
+
this.log(`RTC: Connection established with client ${client.ID}`)
|
|
982
991
|
} else if (
|
|
983
992
|
peerConnection.connectionState === 'failed' ||
|
|
984
993
|
peerConnection.connectionState === 'disconnected' ||
|
|
985
994
|
peerConnection.connectionState === 'closed'
|
|
986
995
|
) {
|
|
987
996
|
client.webRTCConnected = false
|
|
988
|
-
|
|
997
|
+
this.log(`RTC: Connection failed or closed with client ${client.ID}`)
|
|
989
998
|
}
|
|
990
999
|
}
|
|
991
1000
|
|
|
992
1001
|
peerConnection.onicegatheringstatechange = () => {
|
|
993
|
-
//
|
|
1002
|
+
//this.log(`RTC: ICE gathering state: ${peerConnection.iceGatheringState}`);
|
|
994
1003
|
}
|
|
995
1004
|
|
|
996
1005
|
peerConnection.oniceconnectionstatechange = () => {
|
|
997
|
-
//
|
|
1006
|
+
//this.log(`RTC: ICE connection state: ${peerConnection.iceConnectionState}`);
|
|
998
1007
|
if (
|
|
999
1008
|
peerConnection.iceConnectionState === 'connected' ||
|
|
1000
1009
|
peerConnection.iceConnectionState === 'completed'
|
|
1001
1010
|
) {
|
|
1002
|
-
//
|
|
1011
|
+
//this.log(`RTC: ICE connection established with client ${client.ID}`);
|
|
1003
1012
|
}
|
|
1004
1013
|
}
|
|
1005
1014
|
|
|
@@ -1007,7 +1016,7 @@ var TopazCubeServer = class {
|
|
|
1007
1016
|
await peerConnection.setRemoteDescription(
|
|
1008
1017
|
new wrtc.RTCSessionDescription(data)
|
|
1009
1018
|
)
|
|
1010
|
-
//
|
|
1019
|
+
//this.log("RTC: Remote description set successfully");
|
|
1011
1020
|
|
|
1012
1021
|
client.dataChannel = peerConnection.createDataChannel('serverchannel', {
|
|
1013
1022
|
ordered: true,
|
|
@@ -1015,13 +1024,13 @@ var TopazCubeServer = class {
|
|
|
1015
1024
|
})
|
|
1016
1025
|
|
|
1017
1026
|
client.dataChannel.onopen = () => {
|
|
1018
|
-
//
|
|
1027
|
+
//this.log(`RTC: Data channel opened for client ${client.ID}`);
|
|
1019
1028
|
// Try sending a test message
|
|
1020
1029
|
try {
|
|
1021
1030
|
const testData = { c: 'test', message: 'Hello WebRTC' }
|
|
1022
1031
|
this.sendRTC(client, testData)
|
|
1023
1032
|
} catch (e) {
|
|
1024
|
-
|
|
1033
|
+
this.error(
|
|
1025
1034
|
`RTC: Error sending test message to client ${client.ID}`,
|
|
1026
1035
|
e
|
|
1027
1036
|
)
|
|
@@ -1029,23 +1038,23 @@ var TopazCubeServer = class {
|
|
|
1029
1038
|
}
|
|
1030
1039
|
|
|
1031
1040
|
client.dataChannel.onclose = () => {
|
|
1032
|
-
|
|
1041
|
+
this.log(`RTC: Data channel closed for client ${client.ID}`)
|
|
1033
1042
|
}
|
|
1034
1043
|
|
|
1035
1044
|
client.dataChannel.onerror = (error: Event) => {
|
|
1036
|
-
|
|
1045
|
+
this.error(`RTC: Data channel error for client ${client.ID}:`, error)
|
|
1037
1046
|
}
|
|
1038
1047
|
|
|
1039
1048
|
client.dataChannel.onmessage = (event: MessageEvent) => {
|
|
1040
1049
|
try {
|
|
1041
1050
|
const data = decode(event.data)
|
|
1042
|
-
|
|
1051
|
+
this.log(
|
|
1043
1052
|
`RTC: Data channel message from client ${client.ID}:`,
|
|
1044
1053
|
data
|
|
1045
1054
|
)
|
|
1046
1055
|
//this.onMessage(client, data);
|
|
1047
1056
|
} catch (error) {
|
|
1048
|
-
|
|
1057
|
+
this.error(
|
|
1049
1058
|
`RTC: Error decoding message from client ${client.ID}:`,
|
|
1050
1059
|
error
|
|
1051
1060
|
)
|
|
@@ -1056,14 +1065,14 @@ var TopazCubeServer = class {
|
|
|
1056
1065
|
const answer = await peerConnection.createAnswer()
|
|
1057
1066
|
await peerConnection.setLocalDescription(answer)
|
|
1058
1067
|
|
|
1059
|
-
//
|
|
1068
|
+
//this.log(`RTC: Sending answer to client ${client.ID}`);
|
|
1060
1069
|
this.send(client, {
|
|
1061
1070
|
c: 'rtc-answer',
|
|
1062
1071
|
type: answer.type,
|
|
1063
1072
|
sdp: answer.sdp,
|
|
1064
1073
|
})
|
|
1065
1074
|
} catch (error) {
|
|
1066
|
-
|
|
1075
|
+
this.error(
|
|
1067
1076
|
`RTC: Error processing offer from client ${client.ID}:`,
|
|
1068
1077
|
error
|
|
1069
1078
|
)
|
|
@@ -1071,19 +1080,19 @@ var TopazCubeServer = class {
|
|
|
1071
1080
|
}
|
|
1072
1081
|
|
|
1073
1082
|
async _processICECandidate(client: ClientType, data: any): Promise<void> {
|
|
1074
|
-
//
|
|
1083
|
+
//this.log(`RTC: Processing ICE candidate from client ${client.ID}`);
|
|
1075
1084
|
try {
|
|
1076
1085
|
if (client.peerConnection && data.candidate) {
|
|
1077
1086
|
await client.peerConnection.addIceCandidate(
|
|
1078
1087
|
data.candidate
|
|
1079
1088
|
//new wrtc.RTCIceCandidate(data.candidate)
|
|
1080
1089
|
)
|
|
1081
|
-
//
|
|
1090
|
+
//this.log(`RTC: ICE candidate added successfully for client ${client.ID}`);
|
|
1082
1091
|
} else {
|
|
1083
|
-
//
|
|
1092
|
+
//this.warn(`RTC: Cannot add ICE candidate for client ${client.ID} - peerConnection not ready or candidate missing`);
|
|
1084
1093
|
}
|
|
1085
1094
|
} catch (error) {
|
|
1086
|
-
|
|
1095
|
+
this.error(`RTC: Error adding ICE candidate for client ${client.ID}`)
|
|
1087
1096
|
}
|
|
1088
1097
|
}
|
|
1089
1098
|
|
|
@@ -1133,7 +1142,7 @@ var TopazCubeServer = class {
|
|
|
1133
1142
|
|
|
1134
1143
|
|
|
1135
1144
|
if (data.length > 16384) {
|
|
1136
|
-
|
|
1145
|
+
this.log(`BroadcastRTC message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)
|
|
1137
1146
|
}
|
|
1138
1147
|
|
|
1139
1148
|
let packages = this._splitRTCMessage(data)
|
|
@@ -1163,7 +1172,7 @@ var TopazCubeServer = class {
|
|
|
1163
1172
|
let packages: Uint8Array[]
|
|
1164
1173
|
if (data.byteLength > 65535) {
|
|
1165
1174
|
const now = Date.now()
|
|
1166
|
-
|
|
1175
|
+
this.warn(`RTC: Message too large: ${data.byteLength} bytes`)
|
|
1167
1176
|
// Split the message into smaller packages
|
|
1168
1177
|
packages = [];
|
|
1169
1178
|
let offset = 0;
|
|
@@ -1191,10 +1200,10 @@ var TopazCubeServer = class {
|
|
|
1191
1200
|
seq++;
|
|
1192
1201
|
}
|
|
1193
1202
|
|
|
1194
|
-
|
|
1203
|
+
this.log(`RTC: Large message split into ${packages.length} packages`);
|
|
1195
1204
|
} else {
|
|
1196
1205
|
packages = [data]
|
|
1197
|
-
|
|
1206
|
+
this.log(`RTC: Message - ${data.byteLength} bytes`)
|
|
1198
1207
|
}
|
|
1199
1208
|
return packages
|
|
1200
1209
|
}
|
|
@@ -1217,16 +1226,16 @@ var TopazCubeServer = class {
|
|
|
1217
1226
|
this.mongoClient = new import_mongodb.MongoClient(this.MongoUrl);
|
|
1218
1227
|
try {
|
|
1219
1228
|
await this.mongoClient.connect();
|
|
1220
|
-
|
|
1229
|
+
this.log("Connected to MongoDB");
|
|
1221
1230
|
const db = this.mongoClient.db(this.database);
|
|
1222
1231
|
this.DB = db;
|
|
1223
1232
|
} catch (error) {
|
|
1224
|
-
|
|
1233
|
+
this.error("Error connecting to MongoDB:", error);
|
|
1225
1234
|
this.mongoClient = null;
|
|
1226
1235
|
}
|
|
1227
1236
|
}
|
|
1228
1237
|
async _loadDocument(name) {
|
|
1229
|
-
|
|
1238
|
+
this.log(`Loading document '${name}' from MongoDB`);
|
|
1230
1239
|
if (this.DB) {
|
|
1231
1240
|
try {
|
|
1232
1241
|
const doc = await this.DB.collection(this.collection).findOne({
|
|
@@ -1237,10 +1246,10 @@ var TopazCubeServer = class {
|
|
|
1237
1246
|
this.documents[name] = doc;
|
|
1238
1247
|
}
|
|
1239
1248
|
} catch (error) {
|
|
1240
|
-
|
|
1249
|
+
this.error("Error loading document from MongoDB:", error);
|
|
1241
1250
|
}
|
|
1242
1251
|
} else {
|
|
1243
|
-
|
|
1252
|
+
this.warn("MongoDB client not initialized. Document not loaded.");
|
|
1244
1253
|
}
|
|
1245
1254
|
}
|
|
1246
1255
|
async _saveDocument(name) {
|
|
@@ -1248,18 +1257,18 @@ var TopazCubeServer = class {
|
|
|
1248
1257
|
try {
|
|
1249
1258
|
const doc = this.documents[name];
|
|
1250
1259
|
let newdoc = clonewo_(doc, "__");
|
|
1251
|
-
|
|
1260
|
+
this.log(`Saving document '${name}' to MongoDB`);
|
|
1252
1261
|
await this.DB.collection(this.collection).updateOne(
|
|
1253
1262
|
{ name },
|
|
1254
1263
|
{ $set: newdoc },
|
|
1255
1264
|
{ upsert: true }
|
|
1256
1265
|
);
|
|
1257
|
-
|
|
1266
|
+
this.log("Document saved to MongoDB");
|
|
1258
1267
|
} catch (error) {
|
|
1259
|
-
|
|
1268
|
+
this.error("Error saving document to MongoDB:", error);
|
|
1260
1269
|
}
|
|
1261
1270
|
} else {
|
|
1262
|
-
|
|
1271
|
+
this.warn("MongoDB client not initialized. Document not saved.");
|
|
1263
1272
|
}
|
|
1264
1273
|
}
|
|
1265
1274
|
async _saveAllDocuments() {
|
|
@@ -1278,7 +1287,7 @@ var TopazCubeServer = class {
|
|
|
1278
1287
|
/*= EXIT ===================================================================*/
|
|
1279
1288
|
_exitSignal(signal) {
|
|
1280
1289
|
if (!this._exited) {
|
|
1281
|
-
|
|
1290
|
+
this.log("\nEXIT: Caught interrupt signal " + signal);
|
|
1282
1291
|
this._exited = true;
|
|
1283
1292
|
clearInterval(this._loopiv);
|
|
1284
1293
|
this.onBeforeExit();
|