teleportxr 1.0.16 → 1.0.17

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/client/client.js CHANGED
@@ -140,6 +140,13 @@ class Client {
140
140
  // function(value) {myDisplayer(value);},
141
141
  // function(error) {myDisplayer(error);}
142
142
  }
143
+ //! Cleanly shut down the WebRTC connection. This may be called when the client has signalled that it is
144
+ //! disconnecting, or when the server determines that the client is lost or needs to be booted.
145
+ StopStreaming()
146
+ {
147
+ this.webRtcConnectionManager.destroyConnection(this.clientID);
148
+ this.webRtcConnection=null;
149
+ }
143
150
  // Generic message acknowledgement. Certain kinds of message are expected to be ack'ed.
144
151
  ReceiveAcknowledgement(data)
145
152
  {
@@ -239,6 +246,7 @@ class Client {
239
246
  if(!this.webRtcConnection.sendGeometry)
240
247
  {
241
248
  console.error("this.webRtcConnection.sendGeometry is null");
249
+ console.log(JSON.stringify(this.webRtcConnection));
242
250
  return;
243
251
  }
244
252
  this.webRtcConnection.sendGeometry(view2);
@@ -94,6 +94,13 @@ class ClientManager
94
94
  c.Start();
95
95
  return c;
96
96
  }
97
+ disconnectClient(clientID) {
98
+ // then we tell the client manager to start this client.
99
+ var c=this.GetClient(clientID);
100
+ if(!c)
101
+ return;
102
+ c.StopStreaming();
103
+ }
97
104
  writeState() {
98
105
  var content="<table><tr><th>Client Id</th><th>IP Address</th><th>Signalling State</th></tr>";
99
106
  for (let [cl_id,cl] of this.clients) {
@@ -46,7 +46,6 @@ class WebRtcConnection extends EventEmitter
46
46
  timeToReconnected
47
47
  } = options;
48
48
 
49
- this.connectionStateChanged =options.connectionStateChanged;
50
49
  this.messageReceivedReliableCb =options.messageReceivedReliable;
51
50
  this.messageReceivedUnreliableCb =options.messageReceivedUnreliable;
52
51
 
@@ -86,7 +85,7 @@ class WebRtcConnection extends EventEmitter
86
85
  {
87
86
  this.peerConnection =new DefaultRTCPeerConnection({ sdpSemantics: 'unified-plan', 'iceServers': this.iceServers});
88
87
  this.beforeOffer();
89
- let connectionTimer = this.options.setTimeout(() =>
88
+ this.connectionTimer = this.options.setTimeout(() =>
90
89
  {
91
90
  if (this.peerConnection.iceConnectionState !== 'connected'
92
91
  && this.peerConnection.iceConnectionState !== 'completed')
@@ -96,55 +95,16 @@ class WebRtcConnection extends EventEmitter
96
95
  }
97
96
  }, this.options.timeToConnected);
98
97
 
99
- let reconnectionTimer = null;
98
+ this.reconnectionTimer = null;
100
99
 
101
- const onIceConnectionStateChange = () =>
102
- {
103
- console.log("ICE state changed to: "+this.peerConnection.iceConnectionState);
104
- if (this.peerConnection.iceConnectionState === 'connected'
105
- || this.peerConnection.iceConnectionState === 'completed')
106
- {
107
- if (connectionTimer)
108
- {
109
- this.options.clearTimeout(connectionTimer);
110
- connectionTimer = null;
111
- }
112
- this.options.clearTimeout(reconnectionTimer);
113
- reconnectionTimer = null;
114
- } else if (this.peerConnection.iceConnectionState === 'disconnected'
115
- || this.peerConnection.iceConnectionState === 'failed')
116
- {
117
- this.peerConnection.restartIce();
118
- console.log("restartIce()");
119
- if (!connectionTimer && !reconnectionTimer)
120
- {
121
- const self = this;
122
- reconnectionTimer = this.options.setTimeout(() =>
123
- {
124
- this.reconnect();
125
- this.doOffer();
126
- }, this.options.timeToReconnected);
127
- }
128
- }
129
- };
130
- const onIceGatheringStateChange = () =>
131
- {
132
- console.log("ICE gathering state changed to: "+this.peerConnection.iceGatheringState);
133
- };
134
-
135
- this.peerConnection.addEventListener('iceconnectionstatechange', onIceConnectionStateChange);
136
- this.peerConnection.addEventListener('icegatheringstatechange', onIceGatheringStateChange);
100
+ this.peerConnection.addEventListener('iceconnectionstatechange', this.onIceConnectionStateChange.bind(this));
101
+ this.peerConnection.addEventListener('icegatheringstatechange', this.onIceGatheringStateChange.bind(this));
137
102
  this.peerConnection.addEventListener("icecandidateerror", (event) => {
138
103
 
139
104
  console.log("ICE candidate error: "+event.errorCode+" "+event.errorText+" "+event.port+" "+event.url);
140
105
  });
141
106
 
142
- const onConnectionStateChange = () =>
143
- {
144
- console.log("Connection State changed to: "+this.peerConnection.connectionState.toString());
145
- this.connectionStateChanged(this,this.peerConnection.connectionState);
146
- }
147
- this.peerConnection.addEventListener("connectionstatechange", onConnectionStateChange);
107
+ this.peerConnection.addEventListener("connectionstatechange", this.connectionStateChanged.bind(this,this.peerConnection.connectionState));
148
108
 
149
109
  this.onIceCandidate= ({ candidate })=>
150
110
  {
@@ -179,11 +139,11 @@ class WebRtcConnection extends EventEmitter
179
139
 
180
140
  this.timeout = options.setTimeout(() =>
181
141
  {
182
- peerConnection.removeEventListener('icecandidate', this.onIceCandidate);
142
+ peerConnection.removeEventListener('icecandidate', this.onIceCandidate.bind(this));
183
143
  this.deferred.reject(new Error('Timed out waiting for host candidates'));
184
144
  }, timeToHostCandidates);
185
145
 
186
- peerConnection.addEventListener('icecandidate', this.onIceCandidate);
146
+ peerConnection.addEventListener('icecandidate', this.onIceCandidate.bind(this));
187
147
 
188
148
  await this.deferred.promise;
189
149
  }
@@ -234,24 +194,6 @@ class WebRtcConnection extends EventEmitter
234
194
  console.log(`Failure during addIceCandidate(): ${e.name}`);
235
195
  });
236
196
  };
237
- this.close = () =>
238
- {
239
- console.log("WebRtcConnection.close()");
240
- this.peerConnection.removeEventListener('iceconnectionstatechange', onIceConnectionStateChange);
241
- if (connectionTimer)
242
- {
243
- this.options.clearTimeout(connectionTimer);
244
- connectionTimer = null;
245
- }
246
- if (reconnectionTimer)
247
- {
248
- this.options.clearTimeout(reconnectionTimer);
249
- reconnectionTimer = null;
250
- }
251
- this.peerConnection.close();
252
- this.state = 'closed';
253
- this.emit('closed');
254
- };
255
197
 
256
198
  this.toJSON = () =>
257
199
  {
@@ -265,6 +207,96 @@ class WebRtcConnection extends EventEmitter
265
207
  };
266
208
  };
267
209
  }
210
+ connectionStateChanged()
211
+ {
212
+ if(!this.peerConnection)
213
+ return;
214
+ console.log("Connection State changed to: "+this.peerConnection.connectionState.toString());
215
+ }
216
+ onIceConnectionStateChange()
217
+ {
218
+ if(!this.peerConnection)
219
+ return;
220
+ console.log("ICE state changed to: "+this.peerConnection.iceConnectionState);
221
+ if (this.peerConnection.iceConnectionState === 'connected'
222
+ || this.peerConnection.iceConnectionState === 'completed')
223
+ {
224
+ if (this.connectionTimer)
225
+ {
226
+ this.options.clearTimeout(this.connectionTimer);
227
+ this.connectionTimer = null;
228
+ }
229
+ this.options.clearTimeout(this.reconnectionTimer);
230
+ this.reconnectionTimer = null;
231
+ } else if (this.peerConnection.iceConnectionState === 'disconnected'
232
+ || this.peerConnection.iceConnectionState === 'failed')
233
+ {
234
+ this.peerConnection.restartIce();
235
+ console.log("restartIce()");
236
+ if (!this.connectionTimer && !this.reconnectionTimer)
237
+ {
238
+ const self = this;
239
+ this.reconnectionTimer = this.options.setTimeout(() =>
240
+ {
241
+ this.reconnect();
242
+ this.doOffer();
243
+ }, this.options.timeToReconnected);
244
+ }
245
+ }
246
+ }
247
+ onIceGatheringStateChange()
248
+ {
249
+ // This could get hit in the WebRtcConnection constructor where we've had no chance to set the peerConnection pointer!
250
+ if(this.peerConnection)
251
+ console.log("ICE gathering state changed to: "+this.peerConnection.iceGatheringState);
252
+ }
253
+
254
+ close()
255
+ {
256
+ console.log("WebRtcConnection.close()");
257
+ if(this.peerConnection)
258
+ {
259
+ this.peerConnection.removeEventListener('iceconnectionstatechange', this.onIceConnectionStateChange.bind(this));
260
+
261
+ this.peerConnection.eve
262
+ this.peerConnection.removeEventListener('iceconnectionstatechange', this.onIceConnectionStateChange.bind(this));
263
+ this.peerConnection.removeEventListener('icegatheringstatechange', this.onIceGatheringStateChange.bind(this));
264
+ //this.peerConnection.removeEventListener("icecandidateerror", (event) => {
265
+ this.peerConnection.removeEventListener("connectionstatechange", this.connectionStateChanged.bind(this,this.peerConnection.connectionState));
266
+ }
267
+ if (this.connectionTimer)
268
+ {
269
+ this.options.clearTimeout(this.connectionTimer);
270
+ this.connectionTimer = null;
271
+ }
272
+ if (this.reconnectionTimer)
273
+ {
274
+ this.options.clearTimeout(this.reconnectionTimer);
275
+ this.reconnectionTimer = null;
276
+ }
277
+
278
+ // Check the connection state
279
+ if(this.peerConnection)
280
+ if (this.peerConnection.connectionState == "connected" ||
281
+ this.peerConnection.connectionState == "failed")
282
+ {
283
+ // Close each track
284
+ /* this.peerConnection.cl.forEach(mediaStream => { {
285
+ mediaStream.videoTracks.forEach( it => {it.setEnabled(false); });
286
+ mediaStream.audioTracks.forEach( it => {it.setEnabled(false); });
287
+
288
+ };
289
+ });;6'7*/
290
+
291
+ // Close the connection
292
+ this.peerConnection.close();
293
+ }
294
+
295
+ // Nullify the reference
296
+ this.peerConnection = null;
297
+ this.state = 'closed';
298
+ this.emit('closed');
299
+ };
268
300
  sendGeometry(buffer) {
269
301
  try {
270
302
  this.geometryDataChannel.send(buffer);
@@ -281,7 +313,6 @@ class WebRtcConnection extends EventEmitter
281
313
  this.geometryDataChannel = this.createDataChannel("geometry_unframed",80);
282
314
  this.reliableDataChannel = this.createDataChannel("reliable",100);
283
315
  this.unreliableDataChannel = this.createDataChannel("unreliable",120,false);
284
- // this.dataChannel = this.peerConnection.createDataChannel('ping-pong',{id:2050});
285
316
 
286
317
  function onMessage({ data }) {
287
318
  if (data === 'ping') {
@@ -6,56 +6,65 @@ class WebRtcConnectionManager
6
6
  {
7
7
  constructor(options = {})
8
8
  {
9
- options = {
10
- Connection: WebRtcConnection,
11
- ...options
12
- };
13
- const { Connection } = options;
14
- const connections = new Map();
15
- const closedListeners = new Map();
9
+ this.connections = new Map();
10
+ this.closedListeners = new Map();
11
+ this.options=options;
12
+ }
16
13
 
17
- function deleteConnection(connection) {
14
+ deleteConnection(connection)
15
+ {
16
+ console.log("deleteConnection "+connection.clientID);
18
17
  // 1. Remove "closed" listener?
19
- //const closedListener = closedListeners.get(connection);
18
+ //const closedListener = this.closedListeners.get(connection);
20
19
  //connection.removeListener("closed", closedListener);
21
- //closedListeners.delete(connection);
20
+ //this.closedListeners.delete(connection);
21
+
22
+ // 2. Remove the WebRtcConnection from the Map.
23
+ this.connections.delete(connection.id);
24
+ }
25
+ getConnection(id)
26
+ {
27
+ return this.connections.get(id) || null;
28
+ }
29
+
30
+ getConnections()
31
+ {
32
+ return [...this.connections.values()];
33
+ };
22
34
 
23
- // 2. Remove the Connection from the Map.
24
- connections.delete(connection.id);
25
- }
26
35
 
27
- this.createConnection = (clientID,connectionStateChangedcb,messageReceivedReliableCb,messageReceivedUnreliableCb) =>
36
+ closedListener()
37
+ {
38
+ this.deleteConnection(connection);
39
+ }
40
+ createConnection(clientID,connectionStateChangedcb,messageReceivedReliableCb,messageReceivedUnreliableCb)
28
41
  {
42
+ var options=this.options;
29
43
  options.sendConfigMessage =this.sendConfigMessage;
30
44
 
31
45
  options.messageReceivedReliable =messageReceivedReliableCb;
32
46
  options.messageReceivedUnreliable =messageReceivedUnreliableCb;
33
- const connection = new Connection(clientID,options);
47
+ const connection = new WebRtcConnection(clientID,options);
34
48
  connection.connectionStateChanged=connectionStateChangedcb;
35
- // 1. Add the "closed" listener.
36
- function closedListener() { deleteConnection(connection); }
37
- this.createConnection = (clientID) =>
38
- closedListeners.set(connection, closedListener);
39
- connection.once('closed', closedListener);
49
+ // We will not add a "closed" listener, because only the client object will be permitted to close its connection.
50
+ //this.createConnection = (clientID) => this.closedListeners.set(connection, this.closedListener);
51
+ //connection.once('closed', this.closedListener);
40
52
 
41
- // 2. Add the Connection to the Map.
42
- connections.set(connection.id, connection);
53
+ // 2. Add the WebRtcConnection to the Map.
54
+ this.connections.set(connection.id, connection);
43
55
 
44
56
  connection.doOffer();
45
57
  return connection;
46
58
  };
47
-
48
- this.getConnection = id =>
59
+ destroyConnection(clientID)
49
60
  {
50
- return connections.get(id) || null;
51
- };
52
-
53
- this.getConnections = () =>
61
+ var connection=this.connections.get(clientID);
62
+ if(connection)
54
63
  {
55
- return [...connections.values()];
56
- };
64
+ connection.close();
65
+ this.connections.delete(clientID);
57
66
  }
58
-
67
+ }
59
68
  toJSON ()
60
69
  {
61
70
  return this.getConnections().map(connection => connection.toJSON());
@@ -69,7 +78,7 @@ class WebRtcConnectionManager
69
78
  WebRtcConnectionManager.create = function create (options)
70
79
  {
71
80
  return new WebRtcConnectionManager({
72
- Connection: function (id)
81
+ WebRtcConnection: function (id)
73
82
  {
74
83
  return new WebRtcConnection(id,options);
75
84
  },
package/index.js CHANGED
@@ -7,7 +7,7 @@ function initServer(signaling_port) {
7
7
  var cm=client_manager.getInstance();
8
8
  const webRtcConnectionManager = WebRtcConnectionManager.getInstance();
9
9
  webRtcConnectionManager.SetSendConfigMessage(signaling.sendConfigMessage);
10
- return signaling.init(webRtcConnectionManager,cm.newClient.bind(cm),signaling_port);
10
+ return signaling.init(webRtcConnectionManager,cm.newClient.bind(cm),cm.disconnectClient.bind(cm),signaling_port);
11
11
  }
12
12
 
13
13
  module.exports = {initServer}
package/package.json CHANGED
@@ -13,7 +13,7 @@
13
13
  },
14
14
  "name": "teleportxr",
15
15
  "description": "Teleport Spatial Server on node.js",
16
- "version": "1.0.16",
16
+ "version": "1.0.17",
17
17
  "repository": {
18
18
  "type": "git",
19
19
  "url": "git+https://github.com/simul/teleport-nodejs.git"
package/signaling.js CHANGED
@@ -11,6 +11,7 @@ class SignalingState {
11
11
  static ACCEPTED = new SignalingState("Accepted");
12
12
  static STREAMING = new SignalingState("Streaming");
13
13
  static INVALID = new SignalingState("Invalid");
14
+ static STOP = new SignalingState("Stop");
14
15
 
15
16
  constructor(name) {
16
17
  this.name = name;
@@ -49,6 +50,7 @@ var signalingClients = new Map();
49
50
  var desiredIP = "";
50
51
  var webRtcConnectionManager = null;
51
52
  var newClient=null;
53
+ var disconnectClient=null;
52
54
  function startStreaming(signalingClient) {
53
55
  signalingClient.ChangeSignalingState(SignalingState.ACCEPTED);
54
56
  // And we send the WebSockets request-response.
@@ -70,7 +72,9 @@ function sendResponseToClient(clientID) {
70
72
  }
71
73
  }
72
74
  function processDisconnection(clientID,signalingClient){
73
-
75
+ signalingClient.ChangeSignalingState(SignalingState.START);
76
+ disconnectClient(signalingClient.clientID);
77
+ signalingClients.delete(clientID);
74
78
  }
75
79
  function processInitialRequest(clientID, signalingClient, content) {
76
80
  var j_clientID = 0;
@@ -217,7 +221,7 @@ function OnWebSocket(ws, req) {
217
221
  console.log("Some Error occurred");
218
222
  };
219
223
  }
220
- exports.init = function (webRtcCM, newClientFn, signaling_port) {
224
+ exports.init = function (webRtcCM, newClientFn, disconnectClientFn, signaling_port) {
221
225
  // Creating a new websocket server
222
226
  // const signaling_port = process.env.PORT || 8081;
223
227
  var wss;
@@ -231,6 +235,7 @@ exports.init = function (webRtcCM, newClientFn, signaling_port) {
231
235
  }
232
236
  webRtcConnectionManager = webRtcCM;
233
237
  newClient=newClientFn;
238
+ disconnectClient=disconnectClientFn;
234
239
  // Creating connection using websocket
235
240
  wss.on("connection", (ws, req) => {
236
241
  OnWebSocket(ws, req);