topazcube 0.1.21 → 0.1.22

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/src/client.ts CHANGED
@@ -32,6 +32,7 @@ interface ConstructorParams {
32
32
  autoReconnect?: boolean; // auto reconnect on disconnect
33
33
  allowSync?: boolean; // allow sync on connect
34
34
  allowWebRTC?: boolean;
35
+ DEBUG?: boolean;
35
36
  }
36
37
 
37
38
  interface Message {
@@ -180,7 +181,7 @@ declare global {
180
181
  }
181
182
 
182
183
  export default class TopazCubeClient {
183
- debug = false
184
+ DEBUG = false
184
185
  CYCLE = 200 // update/patch rate in ms
185
186
  url = ''
186
187
  documents: { [key: string]: Document } = {}
@@ -211,6 +212,9 @@ export default class TopazCubeClient {
211
212
  ID = 0
212
213
  socket: WebSocket | null = null
213
214
  _peerConnection: RTCPeerConnection | null = null
215
+ _candidates: RTCIceCandidate[] = []
216
+ _remoteCandidates: RTCIceCandidateInit[] = []
217
+ _offerSent: boolean = false
214
218
  _dataChannel: RTCDataChannel | null = null // our data channel
215
219
  _serverDataChannel: RTCDataChannel | null = null // server data channel
216
220
  _webRTCConnected: boolean = false
@@ -233,14 +237,32 @@ export default class TopazCubeClient {
233
237
  autoReconnect = true, // auto reconnect on disconnect
234
238
  allowSync = true, // allow sync on connect
235
239
  allowWebRTC = false,
240
+ DEBUG = false
236
241
  }: ConstructorParams) {
237
242
  this.url = url
238
243
  this.autoReconnect = autoReconnect
239
244
  this.allowSync = allowSync
240
245
  this.allowWebRTC = allowWebRTC
241
246
  this.socket = null
247
+ this.DEBUG = DEBUG
242
248
  this._startLoop()
243
- console.log('Client initialized')
249
+ this.log('Client initialized')
250
+ }
251
+
252
+ log(...args: any[]) {
253
+ if (this.DEBUG) {
254
+ console.log(...args);
255
+ }
256
+ }
257
+
258
+ warn(...args: any[]) {
259
+ if (this.DEBUG) {
260
+ console.warn(...args);
261
+ }
262
+ }
263
+
264
+ error(...args: any[]) {
265
+ console.error(...args);
244
266
  }
245
267
 
246
268
  /*= UPDATE ===================================================================*/
@@ -354,7 +376,7 @@ export default class TopazCubeClient {
354
376
  }
355
377
  this.isConnecting = true
356
378
  this._clear()
357
- console.log('connecting...')
379
+ this.log('connecting...')
358
380
 
359
381
  this.socket = new WebSocket(this.url)
360
382
 
@@ -475,7 +497,7 @@ export default class TopazCubeClient {
475
497
  this.socket.send(enc)
476
498
  }
477
499
  } catch (e) {
478
- console.error('send failed', e)
500
+ this.error('send failed', e)
479
501
  }
480
502
  }
481
503
 
@@ -487,7 +509,7 @@ export default class TopazCubeClient {
487
509
  async _onMessage(message: Message) {
488
510
  let time = Date.now()
489
511
  if (message.c == 'full') {
490
- //console.log('full:', message)
512
+ //this.log('full:', message)
491
513
  let name:string = ''+message.n
492
514
  let doc = message.doc
493
515
  this.documents[name] = doc
@@ -517,7 +539,7 @@ export default class TopazCubeClient {
517
539
  try {
518
540
  applyOperation(this.documents[name], dop)
519
541
  } catch (e) {
520
- console.error('applyOperation failed for', name, 'with op', dop, e)
542
+ this.error('applyOperation failed for', name, 'with op', dop, e)
521
543
  }
522
544
  }
523
545
  this.isPatched = false
@@ -526,7 +548,7 @@ export default class TopazCubeClient {
526
548
  this.onChange(name, this.documents[name], message.doc)
527
549
  }
528
550
  } else if (message.c == 'chunk') {
529
- //console.log('chunk', message)
551
+ //this.log('chunk', message)
530
552
  this._chunks[message.mid+'-'+message.seq] = message
531
553
  if (message.last) {
532
554
  let cfound = 0
@@ -542,25 +564,25 @@ export default class TopazCubeClient {
542
564
  delete this._chunks[cid]
543
565
  }
544
566
  }
545
- //console.log('found chunks ', cfound, 'of', message.seq + 1)
567
+ //this.log('found chunks ', cfound, 'of', message.seq + 1)
546
568
  if (cfound == message.seq + 1) {
547
569
  try {
548
570
  let cdec = await decompress(cdata)
549
571
  let cdecu = new Uint8Array(cdec)
550
572
  let nmessage = decode(cdecu)
551
- //console.log('decoded message', nmessage)
573
+ //this.log('decoded message', nmessage)
552
574
  this._onMessage(nmessage)
553
575
  } catch (error) {
554
- console.error('Error decoding chunks:', error)
576
+ this.error('Error decoding chunks:', error)
555
577
  }
556
578
  } else {
557
- console.warn('missing chunks', cfound, 'of', message.seq + 1)
579
+ this.warn('missing chunks', cfound, 'of', message.seq + 1)
558
580
  }
559
581
  }
560
582
  } else if (message.c == 'fpatch') {
561
583
  time = Date.now()
562
584
  let name = message.n
563
- //console.log('fpatch', message)
585
+ //this.log('fpatch', message)
564
586
  let doPatch = true
565
587
  if (!this._lastUpdateId[name]) {
566
588
  this._lastUpdateId[name] = message.u
@@ -568,13 +590,13 @@ export default class TopazCubeClient {
568
590
  if (this._lastUpdateId[name] < message.u) {
569
591
  let lp = message.u - this._lastUpdateId[name] - 1
570
592
  if (lp > 0) {
571
- console.warn('Lost ' + lp + ' updates')
593
+ this.warn('Lost ' + lp + ' updates')
572
594
  }
573
595
  this._lastUpdateId[name] = message.u
574
596
  } else if (this._lastUpdateId[name] > message.u) {
575
597
  // Handle the case where the server's update ID is older than the client's
576
598
  // This could be due to a network issue or a clock skew
577
- console.warn(`Received outdated update ID for document ${name}: ${message.u} < ${this._lastUpdateId[name]}`)
599
+ this.warn(`Received outdated update ID for document ${name}: ${message.u} < ${this._lastUpdateId[name]}`)
578
600
  doPatch = false
579
601
  }
580
602
  }
@@ -590,12 +612,12 @@ export default class TopazCubeClient {
590
612
  this.send({ c: 'peng', ct: Date.now(), st: stime })
591
613
  this.stats.stdiff = stime + ping / 2 - time
592
614
  this.stats.ping = ping
593
- console.log('ping', ping, 'ms', 'stdiff', this.stats.stdiff, 'ms')
615
+ this.log('ping', ping, 'ms', 'stdiff', this.stats.stdiff, 'ms')
594
616
  } else if (message.c == 'rtc-offer') {
595
- //console.log("RTC: offer received:", message);
617
+ this.log("RTC: offer received:", message);
596
618
  // You might need to handle this if the server sends offers
597
619
  } else if (message.c == 'rtc-answer') {
598
- //console.log("RTC: answer received:", message);
620
+ this.log("RTC: answer received:", message);
599
621
  try {
600
622
  const sessionDesc = new RTCSessionDescription({
601
623
  type: message.type,
@@ -604,39 +626,36 @@ export default class TopazCubeClient {
604
626
  if (this._peerConnection) {
605
627
  await this._peerConnection.setRemoteDescription(sessionDesc)
606
628
  }
607
- //console.log("RTC: Remote description set successfully");
629
+ this.log("RTC: Remote description set successfully");
608
630
 
609
631
  // Log the current state after setting remote description
610
- //console.log("RTC: Current connection state:", this._peerConnection.connectionState);
611
- //console.log("RTC: Current ICE connection state:", this._peerConnection.iceConnectionState);
632
+ //
633
+ //this.log("RTC: Current connection state:", this._peerConnection.connectionState);
634
+ //this.log("RTC: Current ICE connection state:", this._peerConnection.iceConnectionState);
635
+ for (let candidate of this._remoteCandidates) {
636
+ try {
637
+ await this._peerConnection?.addIceCandidate(candidate);
638
+ this.log("RTC: Added remote ICE candidate:", candidate);
639
+ } catch (error) {
640
+ this.error("RTC: Error adding remote ICE candidate:", error);
641
+ }
642
+ }
612
643
  } catch (error) {
613
- console.error('RTC: Error setting remote description:', error)
644
+ this.error('RTC: Error setting remote description:', error)
614
645
  }
615
646
  } else if (message.c == 'rtc-candidate') {
616
- //console.log("RTC: candidate received", message);
617
- try {
647
+ this.log("RTC: candidate received", message);
618
648
  if (this._peerConnection && message.candidate) {
619
- await this._peerConnection.addIceCandidate(
620
- //new RTCIceCandidate(message.candidate)
621
- message.candidate
622
- )
623
- //console.log("RTC: ICE candidate added successfully");
624
- } else {
625
- console.warn(
626
- 'RTC: Received candidate but peerConnection not ready or candidate missing'
627
- )
649
+ this._remoteCandidates.push(message.candidate);
628
650
  }
629
- } catch (error) {
630
- //console.error("RTC: Error adding ICE candidate:", error);
631
- }
632
651
  } else {
633
652
  this.onMessage(message)
634
653
  }
635
654
  }
636
655
 
637
656
  _onDocumentChange(name: string, op: any, target: any, path: string, value: any) {
638
- if (this.debug) {
639
- console.log('Document change:', name, op, target, path, value)
657
+ if (this.DEBUG) {
658
+ this.log('Document change:', name, op, target, path, value)
640
659
  }
641
660
  if (this.isPatched || !this.allowSync) {
642
661
  return
@@ -712,12 +731,12 @@ export default class TopazCubeClient {
712
731
  offset += 4
713
732
  let e: Entity = entities[id]
714
733
  if (!e) {
715
- //console.log('Entity not found:', id)
734
+ //this.log('Entity not found:', id)
716
735
  continue
717
736
  }
718
737
  let value = rdict[did]
719
738
  e[key] = value
720
- //console.log('FCHANGE', key, id, did, value, rdict)
739
+ //this.log('FCHANGE', key, id, did, value, rdict)
721
740
  e['_changed_'+key] = time
722
741
  }
723
742
  } else {
@@ -830,13 +849,13 @@ export default class TopazCubeClient {
830
849
  }
831
850
 
832
851
  _onRTCConnect() {
833
- console.log('RTC: Connected')
852
+ this.log('RTC: Connected')
834
853
  this.send({ c: 'test', message: 'Hello RTC from client' })
835
854
  }
836
855
 
837
856
  _onRTCDisconnect() {
838
857
  this._webRTCConnected = false
839
- console.log('RTC: Disconnected')
858
+ this.log('RTC: Disconnected')
840
859
  }
841
860
 
842
861
  async _onRTCMessage(data: ArrayBuffer) {
@@ -849,8 +868,11 @@ export default class TopazCubeClient {
849
868
  }
850
869
 
851
870
  async _initializeWebRTC() {
852
- //console.log("RTC: _initializeWebRTC")
871
+ //this.log("RTC: _initializeWebRTC")
853
872
  this._peerConnection = null
873
+ this._candidates = []
874
+ this._remoteCandidates = []
875
+ this._offerSent = false
854
876
  try {
855
877
  // Create RTCPeerConnection with more comprehensive STUN server list
856
878
  this._peerConnection = new RTCPeerConnection({
@@ -862,27 +884,24 @@ export default class TopazCubeClient {
862
884
  iceCandidatePoolSize: 10,
863
885
  })
864
886
 
865
- //console.log("RTC: peerConnection created", this._peerConnection)
887
+ //this.log("RTC: peerConnection created", this._peerConnection)
866
888
 
867
889
  // Handle ICE candidates
868
890
  this._peerConnection.onicecandidate = (event: RTCPeerConnectionIceEvent) => {
869
- //console.log("RTC: onicecandidate", event.candidate)
891
+ //this.log("RTC: onicecandidate", event.candidate)
870
892
  if (event.candidate) {
871
- this.send({
872
- c: 'rtc-candidate',
873
- type: 'ice-candidate',
874
- candidate: event.candidate,
875
- })
893
+ this._candidates.push(event.candidate)
876
894
  } else {
877
- //console.log("RTC: ICE candidate gathering complete")
895
+ this.log("RTC: ICE candidate gathering complete")
878
896
  }
879
897
  }
880
898
 
881
899
  // Log connection state changes
882
900
  this._peerConnection.onconnectionstatechange = () => {
883
- //console.log(`RTC: Connection state changed: ${this._peerConnection.connectionState}`)
901
+ //this.log(`RTC: Connection state changed: ${this._peerConnection.connectionState}`)
884
902
  if (this._peerConnection && this._peerConnection.connectionState === 'connected') {
885
903
  this._webRTCConnected = true
904
+ this.log('RTC: Peer connection established!')
886
905
  } else if (
887
906
  this._peerConnection && (
888
907
  this._peerConnection.connectionState === 'failed' ||
@@ -890,15 +909,25 @@ export default class TopazCubeClient {
890
909
  this._peerConnection.connectionState === 'closed')
891
910
  ) {
892
911
  this._webRTCConnected = false
912
+ this.log('RTC: Peer connection closed or failed')
893
913
  }
894
914
  }
895
915
 
896
916
  this._peerConnection.onicegatheringstatechange = () => {
897
- //console.log(`RTC: ICE gathering state: ${this._peerConnection.iceGatheringState}`)
917
+ this.log(`RTC: ICE gathering state. _candidates:`, this._candidates.length, this._peerConnection?.iceGatheringState)
918
+ if (this._peerConnection?.iceGatheringState == 'complete' && this._offerSent) {
919
+ for (let candidate of this._candidates) {
920
+ this.send({
921
+ c: 'rtc-candidate',
922
+ type: 'ice-candidate',
923
+ candidate: candidate,
924
+ })
925
+ }
926
+ }
898
927
  }
899
928
 
900
929
  this._peerConnection.oniceconnectionstatechange = () => {
901
- //console.log(`RTC: ICE connection state: ${this._peerConnection.iceConnectionState}`)
930
+ //this.log(`RTC: ICE connection state: ${this._peerConnection.iceConnectionState}`)
902
931
 
903
932
  // This is critical - when ICE succeeds, the connection should be established
904
933
  if (
@@ -906,7 +935,7 @@ export default class TopazCubeClient {
906
935
  this._peerConnection.iceConnectionState === 'connected' ||
907
936
  this._peerConnection.iceConnectionState === 'completed')
908
937
  ) {
909
- //console.log("RTC: ICE connection established!")
938
+ //this.log("RTC: ICE connection established!")
910
939
  }
911
940
  }
912
941
 
@@ -928,25 +957,25 @@ export default class TopazCubeClient {
928
957
  }
929
958
 
930
959
  this._dataChannel.onerror = (_error: Event) => {
931
- console.error('RTC: Client data channel error', _error)
960
+ this.error('RTC: Client data channel error', _error)
932
961
  }
933
962
 
934
963
  // Handle data channels created by the server
935
964
  this._peerConnection.ondatachannel = (event: RTCDataChannelEvent) => {
936
- //console.log("RTC: Server data channel received", event.channel.label);
965
+ //this.log("RTC: Server data channel received", event.channel.label);
937
966
  const dataChannel = event.channel
938
967
  this._serverDataChannel = dataChannel
939
968
 
940
969
  dataChannel.onopen = () => {
941
- //console.log("RTC: Server data channel open");
970
+ //this.log("RTC: Server data channel open");
942
971
  }
943
972
 
944
973
  dataChannel.onclose = () => {
945
- //console.log("RTC: Server data channel closed");
974
+ //this.log("RTC: Server data channel closed");
946
975
  }
947
976
 
948
977
  dataChannel.onerror = (_error: Event) => {
949
- //console.error("RTC: Server data channel error", error);
978
+ //this.error("RTC: Server data channel error", error);
950
979
  }
951
980
 
952
981
  dataChannel.onmessage = (event: MessageEvent) => {
@@ -962,14 +991,14 @@ export default class TopazCubeClient {
962
991
  }
963
992
 
964
993
  const offer = await this._peerConnection.createOffer(offerOptions)
965
- //console.log("RTC: our offer:", offer);
994
+ //this.log("RTC: our offer:", offer);
966
995
  await this._peerConnection.setLocalDescription(offer)
967
996
 
968
997
  // Wait a moment to ensure the local description is set
969
998
  await new Promise((resolve) => setTimeout(resolve, 100))
970
999
 
971
1000
  let ld = this._peerConnection.localDescription
972
- //console.log("RTC: our localDescription", ld);
1001
+ //this.log("RTC: our localDescription", ld);
973
1002
 
974
1003
  if (ld) {
975
1004
  const offerPayload = {
@@ -977,28 +1006,29 @@ export default class TopazCubeClient {
977
1006
  type: ld.type,
978
1007
  sdp: ld.sdp,
979
1008
  }
980
- //console.log("RTC: our offer payload", offerPayload);
1009
+ //this.log("RTC: our offer payload", offerPayload);
981
1010
  this.send(offerPayload)
1011
+ this._offerSent = true
982
1012
  }
983
1013
 
984
1014
  // Set a timeout to check connection status
985
1015
  setTimeout(() => {
986
1016
  if (!this._webRTCConnected && this._peerConnection) {
987
1017
  /*
988
- console.log("RTC: Connection not established after timeout, current states:");
989
- console.log("Connection state:", this._peerConnection.connectionState);
990
- console.log("ICE connection state:", this._peerConnection.iceConnectionState);
991
- console.log("ICE gathering state:", this._peerConnection.iceGatheringState);
1018
+ this.log("RTC: Connection not established after timeout, current states:");
1019
+ this.log("Connection state:", this._peerConnection.connectionState);
1020
+ this.log("ICE connection state:", this._peerConnection.iceConnectionState);
1021
+ this.log("ICE gathering state:", this._peerConnection.iceGatheringState);
992
1022
  */
993
1023
  // Attempt to restart ICE if needed
994
1024
  if (this._peerConnection.iceConnectionState === 'failed') {
995
- console.log('RTC: Attempting ICE restart')
1025
+ this.log('RTC: Attempting ICE restart')
996
1026
  this._restartIce()
997
1027
  }
998
1028
  }
999
1029
  }, 5000)
1000
1030
  } catch (error) {
1001
- console.error('RTC: error:', error)
1031
+ this.error('RTC: error:', error)
1002
1032
  }
1003
1033
  }
1004
1034
 
@@ -1019,10 +1049,10 @@ export default class TopazCubeClient {
1019
1049
  type: offer?.type,
1020
1050
  sdp: offer?.sdp,
1021
1051
  }
1022
- //console.log("RTC: ICE restart offer payload", offerPayload);
1052
+ //this.log("RTC: ICE restart offer payload", offerPayload);
1023
1053
  this.send(offerPayload)
1024
1054
  } catch (error) {
1025
- //console.error("RTC: Error during ICE restart:", error);
1055
+ //this.error("RTC: Error during ICE restart:", error);
1026
1056
  }
1027
1057
  }
1028
1058
 
package/src/server.ts CHANGED
@@ -19,7 +19,7 @@ import fastjsonpatch from 'fast-json-patch'
19
19
  import { WebSocketServer, WebSocket } from 'ws'
20
20
  import { MongoClient, Db } from 'mongodb'
21
21
  import { glMatrix, vec3, quat } from 'gl-matrix'
22
- // WebRTC implementation loaded conditionally when needed
22
+ import { RTCPeerConnection, RTCDataChannel, RTCSessionDescription } from "werift";
23
23
 
24
24
  glMatrix.setMatrixArrayType(Array)
25
25
 
@@ -73,6 +73,7 @@ interface StatsType {
73
73
  }
74
74
 
75
75
  export default class TopazCubeServer {
76
+ DEBUG = false
76
77
  name = 'TopazCubeServer'
77
78
  cycle = 100
78
79
  patchCycleDivider = 1
@@ -91,7 +92,6 @@ export default class TopazCubeServer {
91
92
  allowFastPatch = false
92
93
  allowCompression = false
93
94
  simulateLatency = 0
94
-
95
95
  _lastUID = 100
96
96
  clients: ClientType[] = []
97
97
  documents: Record<string, any> = {}
@@ -118,11 +118,15 @@ export default class TopazCubeServer {
118
118
  _exited = false
119
119
 
120
120
  log(...args: any[]) {
121
+ if (this.DEBUG) {
121
122
  console.log(this.name + ':', ...args);
123
+ }
122
124
  }
123
125
 
124
126
  warn(...args: any[]) {
127
+ if (this.DEBUG) {
125
128
  console.warn(this.name + ':', ...args);
129
+ }
126
130
  }
127
131
 
128
132
  error(...args: any[]) {
@@ -145,6 +149,7 @@ export default class TopazCubeServer {
145
149
  allowFastPatch = false,
146
150
  allowCompression = false,
147
151
  simulateLatency = 0,
152
+ DEBUG = false
148
153
  }: {
149
154
  name?: string
150
155
  cycle?: number
@@ -161,6 +166,7 @@ export default class TopazCubeServer {
161
166
  allowFastPatch?: boolean
162
167
  allowCompression?: boolean
163
168
  simulateLatency?: number
169
+ DEBUG?: boolean
164
170
  } = {}) {
165
171
  this.name = name
166
172
  this.cycle = cycle
@@ -177,6 +183,7 @@ export default class TopazCubeServer {
177
183
  this.allowFastPatch = allowFastPatch
178
184
  this.allowCompression = allowCompression
179
185
  this.simulateLatency = simulateLatency
186
+ this.DEBUG = DEBUG
180
187
 
181
188
  this._initDB()
182
189
 
@@ -786,7 +793,7 @@ export default class TopazCubeServer {
786
793
  n: name,
787
794
  fdata: changes
788
795
  }
789
- //this.broadcastRTC(record, sus)
796
+ this.broadcastRTC(record, sus)
790
797
  let t3 = Date.now()
791
798
  this.log(`_sendPatches: ${name} encode_changes: ${t2-t1}ms broadcast:${t3-t2}ms`)
792
799
  }
@@ -813,19 +820,6 @@ export default class TopazCubeServer {
813
820
 
814
821
  /*= WEBRTC ===================================================================*/
815
822
 
816
- private _wrtc: any = null
817
-
818
- private async _loadWebRTC(): Promise<any> {
819
- if (!this._wrtc) {
820
- try {
821
- this._wrtc = await import('@roamhq/wrtc')
822
- } catch (error) {
823
- this.error('WebRTC module not available:', error)
824
- throw new Error('WebRTC functionality requires @roamhq/wrtc and platform-specific binary packages')
825
- }
826
- }
827
- return this._wrtc
828
- }
829
823
 
830
824
  async _processOffer(client: ClientType, data: any): Promise<void> {
831
825
  if (!this.allowWebRTC) {
@@ -833,34 +827,34 @@ export default class TopazCubeServer {
833
827
  return
834
828
  }
835
829
 
836
- const wrtc = await this._loadWebRTC()
837
- //this.log("RTC: Offer received", data);
838
- const peerConnection = new (wrtc as any).RTCPeerConnection({
830
+ this.log("RTC: Processing offer from client", client.ID, data);
831
+
832
+ const peerConnection = new RTCPeerConnection({
839
833
  iceServers: [
840
834
  { urls: 'stun:stun.l.google.com:19302' },
841
835
  { urls: 'stun:stun.cloudflare.com:3478' },
842
836
  { urls: 'stun:freestun.net:3478' },
843
837
  ],
844
- iceCandidatePoolSize: 10,
838
+ //iceCandidatePoolSize: 10,
845
839
  })
846
840
 
847
841
  client.peerConnection = peerConnection
848
842
 
849
843
  peerConnection.onicecandidate = (event: any) => {
850
844
  if (event.candidate) {
851
- //this.log("RTC: ICE candidate generated", event.candidate.candidate.substring(0, 50) + "...");
845
+ this.log("RTC: ICE candidate generated", event.candidate.candidate.substring(0, 50) + "...");
852
846
  this.send(client, {
853
847
  c: 'rtc-candidate',
854
848
  type: 'ice-candidate',
855
849
  candidate: event.candidate, // .toJSON()
856
850
  })
857
851
  } else {
858
- //this.log("RTC: ICE candidate gathering complete");
852
+ this.log("RTC: ICE candidate gathering complete");
859
853
  }
860
854
  }
861
855
 
862
856
  peerConnection.onconnectionstatechange = () => {
863
- //this.log(`RTC: Connection state changed: ${peerConnection.connectionState}`);
857
+ this.log(`RTC: Connection state changed: ${peerConnection.connectionState}`);
864
858
  if (peerConnection.connectionState === 'connected') {
865
859
  client.webRTCConnected = true
866
860
  this.log(`RTC: Connection established with client ${client.ID}`)
@@ -875,24 +869,26 @@ export default class TopazCubeServer {
875
869
  }
876
870
 
877
871
  peerConnection.onicegatheringstatechange = () => {
878
- //this.log(`RTC: ICE gathering state: ${peerConnection.iceGatheringState}`);
872
+ this.log(`RTC: ICE gathering state: ${peerConnection.iceGatheringState}`);
879
873
  }
880
874
 
881
875
  peerConnection.oniceconnectionstatechange = () => {
882
- //this.log(`RTC: ICE connection state: ${peerConnection.iceConnectionState}`);
876
+ this.log(`RTC: ICE connection state: ${peerConnection.iceConnectionState}`);
883
877
  if (
884
878
  peerConnection.iceConnectionState === 'connected' ||
885
879
  peerConnection.iceConnectionState === 'completed'
886
880
  ) {
887
- //this.log(`RTC: ICE connection established with client ${client.ID}`);
881
+ this.log(`RTC: ICE connection established with client ${client.ID}`);
888
882
  }
889
883
  }
890
884
 
891
885
  try {
886
+ this.log("RTC: Remote description set from data", data);
892
887
  await peerConnection.setRemoteDescription(
893
- new (wrtc as any).RTCSessionDescription(data)
888
+ //data
889
+ new RTCSessionDescription(data.sdp, data.type)
894
890
  )
895
- //this.log("RTC: Remote description set successfully");
891
+ this.log("RTC: Remote description set successfully");
896
892
 
897
893
  client.dataChannel = peerConnection.createDataChannel('serverchannel', {
898
894
  ordered: true,
@@ -900,7 +896,7 @@ export default class TopazCubeServer {
900
896
  })
901
897
 
902
898
  client.dataChannel.onopen = () => {
903
- //this.log(`RTC: Data channel opened for client ${client.ID}`);
899
+ this.log(`RTC: Data channel opened for client ${client.ID}`);
904
900
  // Try sending a test message
905
901
  try {
906
902
  const testData = { c: 'test', message: 'Hello WebRTC' }
@@ -941,7 +937,7 @@ export default class TopazCubeServer {
941
937
  const answer = await peerConnection.createAnswer()
942
938
  await peerConnection.setLocalDescription(answer)
943
939
 
944
- //this.log(`RTC: Sending answer to client ${client.ID}`);
940
+ this.log(`RTC: Sending answer to client ${client.ID}`);
945
941
  this.send(client, {
946
942
  c: 'rtc-answer',
947
943
  type: answer.type,
@@ -956,16 +952,19 @@ export default class TopazCubeServer {
956
952
  }
957
953
 
958
954
  async _processICECandidate(client: ClientType, data: any): Promise<void> {
959
- //this.log(`RTC: Processing ICE candidate from client ${client.ID}`);
955
+ this.log(`RTC: Processing ICE candidate from client ${client.ID}`);
960
956
  try {
957
+ if (data.candidate && typeof(data.candidate) == 'object') {
958
+ data.candidate = data.candidate.candidate
959
+ }
961
960
  if (client.peerConnection && data.candidate) {
962
961
  await client.peerConnection.addIceCandidate(
963
962
  data.candidate
964
963
  //new wrtc.RTCIceCandidate(data.candidate)
965
964
  )
966
- //this.log(`RTC: ICE candidate added successfully for client ${client.ID}`);
965
+ this.log(`RTC: ICE candidate added successfully for client ${client.ID}`);
967
966
  } else {
968
- //this.warn(`RTC: Cannot add ICE candidate for client ${client.ID} - peerConnection not ready or candidate missing`);
967
+ this.warn(`RTC: Cannot add ICE candidate for client ${client.ID} - peerConnection not ready or candidate missing`, client.peerConnection, data);
969
968
  }
970
969
  } catch (error) {
971
970
  this.error(`RTC: Error adding ICE candidate for client ${client.ID}`)