teleportxr 1.0.0

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/signaling.js ADDED
@@ -0,0 +1,255 @@
1
+ 'use strict';
2
+ const getcurrentline = require("get-current-line").default;
3
+
4
+ // Importing the required modules
5
+ const WebSocketServer = require("ws");
6
+ const core=require("./core/core.js");
7
+
8
+ class SignalingState {
9
+ static START = new SignalingState("Start");
10
+ static REQUESTED = new SignalingState("Requested");
11
+ static ACCEPTED = new SignalingState("Accepted");
12
+ static STREAMING = new SignalingState("Streaming");
13
+ static INVALID = new SignalingState("Invalid");
14
+
15
+ constructor(name) {
16
+ this.name = name;
17
+ }
18
+ toString() {
19
+ return `SignalingState.${this.name}`;
20
+ }
21
+ }
22
+
23
+ class SignalingClient {
24
+ constructor(ip, ws, id) {
25
+ this.ip = ip;
26
+ this.ws = ws;
27
+ this.messagesToPassOn = [];
28
+ this.ip_addr_port = "";
29
+ this.signalingState = SignalingState.START;
30
+ this.clientID = id;
31
+ this.receiveReliableBinaryMessage=null;
32
+ }
33
+ ChangeSignalingState(newState) {
34
+ console.log(
35
+ "clientID " +
36
+ this.clientID +
37
+ " signaling state from " +
38
+ this.signalingState +
39
+ " to " +
40
+ newState
41
+ );
42
+ this.signalingState = newState;
43
+ }
44
+ sendToClient(data) {
45
+ this.ws.send(data);
46
+ }
47
+ }
48
+ var signalingClients = new Map();
49
+ var desiredIP = "";
50
+ var webRtcConnectionManager = null;
51
+ var newClient=null;
52
+ function startStreaming(signalingClient) {
53
+ signalingClient.ChangeSignalingState(SignalingState.ACCEPTED);
54
+ // And we send the WebSockets request-response.
55
+ sendResponseToClient(signalingClient.clientID);
56
+ newClient(signalingClient.clientID,signalingClient);
57
+ }
58
+
59
+ function sendResponseToClient(clientID) {
60
+ if (!signalingClients.has(clientID)) {
61
+ console.log("No client "+clientID+" found.");
62
+ } else {
63
+ var signalingClient=signalingClients[clientID];
64
+ // First, we send the WebSockets signaling response.
65
+ var txt =
66
+ '{"teleport-signal-type":"request-response","content":{"clientID": ' +
67
+ signalingClient.clientID +
68
+ '}}';
69
+ signalingClient.ws.send(txt);
70
+ }
71
+ }
72
+ function processDisconnection(clientID,signalingClient){
73
+
74
+ }
75
+ function processInitialRequest(clientID, signalingClient, content) {
76
+ var j_clientID = 0;
77
+ if (content.hasOwnProperty("clientID")) {
78
+ var j_clientID = content["clientID"];
79
+ }
80
+ var thisline = getcurrentline();
81
+ console.log(
82
+ "info: Received connection request from " +
83
+ signalingClient.ip_addr_port +
84
+ " identifying as client " +
85
+ j_clientID +
86
+ " ."
87
+ );
88
+ if (clientID == 0) {
89
+ clientID = j_clientID;
90
+ } else {
91
+ if (!signalingClients.has(j_clientID)) {
92
+ // sent us a client ID that isn't valid. Ignore it, don't waste bandwidth..?
93
+ // or instead, send the replacement ID in the response, leave it up to
94
+ // client whether they accept the new ID or abandon the connection.
95
+ j_clientID = clientID;
96
+ }
97
+ // identifies as a previous client. Discard the new client ID.
98
+ //TODO: we're taking the client's word for it that it is clientID. Some kind of token/hash?
99
+ signalingClients[clientID] = signalingClient;
100
+ if (j_clientID != clientID) {
101
+ console.log(
102
+ "info: Remapped from " + clientID + " to " + j_clientID
103
+ );
104
+ console.log(
105
+ "info: signalingClient has " + signalingClient.clientID
106
+ );
107
+
108
+ if (signalingClients.has(clientID)) {
109
+ signalingClients[clientID] = null;
110
+ clientUids.erase(clientID);
111
+ }
112
+ clientID = j_clientID;
113
+ }
114
+ }
115
+ var ipAddr = signalingClient.ip_addr_port;
116
+ // Skip clients we have already added.
117
+ if (signalingClient.signalingState == SignalingState.START)
118
+ signalingClient.ChangeSignalingState(SignalingState.REQUESTED);
119
+ // if signalingState is START, we should not have a client...
120
+ if (signalingClient.client != null) {
121
+ // ok, we've received a connection request from a client that WE think we already have.
122
+ // Apparently the CLIENT thinks they've disconnected.
123
+ // The client might, as far as we know, have lost the information it needs to continue the connection.
124
+ // Therefore we should resend everything required.
125
+ signalingClient.ChangeSignalingState(SignalingState.STREAMING);
126
+ console.log(
127
+ "Warning: Client " +
128
+ clientID +
129
+ " reconnected, but we didn't know we'd lost them."
130
+ );
131
+ // It may be just that the connection request was already in flight when we accepted its predecessor.
132
+ sendResponseToClient(clientID);
133
+ return;
134
+ }
135
+ if (signalingClient.signalingState != SignalingState.REQUESTED)
136
+ return;
137
+ //Ignore connections from clients with the wrong IP, if a desired IP has been set.
138
+ if (desiredIP.length == 0 || ipAddr.contains(desiredIP)) {
139
+ startStreaming(signalingClient);
140
+ }
141
+ }
142
+
143
+ function receiveWebSocketsMessage(clientID, signalingClient, txt) {
144
+ var message = JSON.parse(txt);
145
+ if (!message.hasOwnProperty("teleport-signal-type"))
146
+ return;
147
+ var teleport_signal_type=message["teleport-signal-type"];
148
+ if (teleport_signal_type == "request")
149
+ {
150
+ processInitialRequest(clientID, signalingClient, message["content"]);
151
+ }
152
+ else if (teleport_signal_type == "disconnect")
153
+ {
154
+ processDisconnection(clientID, signalingClient);
155
+ }
156
+ else
157
+ {
158
+ var webRtcConnection = webRtcConnectionManager.getConnection(clientID);
159
+ if(webRtcConnection)
160
+ webRtcConnection.receiveStreamingControlMessage(txt);
161
+ }
162
+ }
163
+ function OnWebSocket(ws, req) {
164
+ var clientID = core.generateUid();
165
+ var signalingClient = new SignalingClient(
166
+ req.socket.remoteAddress,
167
+ ws,
168
+ clientID
169
+ );
170
+ signalingClient.ip_addr_port = req.socket.remoteAddress;
171
+ signalingClients.set(clientID, signalingClient);
172
+ console.log(
173
+ "new client " +
174
+ clientID.toString() +
175
+ " connected from " +
176
+ signalingClient.ip_addr_port.toString()
177
+ );
178
+ //When the server runs behind a proxy like NGINX, the de-facto standard is to use the X-Forwarded-For header.
179
+ //const ip = .headers['x-forwarded-for'].split(',')[0].trim();
180
+
181
+ const re = RegExp("([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)(:[0-9]+)?", "i");
182
+
183
+ var match = signalingClient.ip_addr_port.match(re);
184
+ if (match) {
185
+ signalingClient.ip_addr_port = match[0];
186
+ }
187
+
188
+ //on message from client
189
+ ws.on("message", (data, isBinary) => {
190
+ if (!isBinary) {
191
+ console.log(`Client has sent text: ${data}`);
192
+ receiveWebSocketsMessage(
193
+ signalingClient.clientID,
194
+ signalingClient,
195
+ data
196
+ );
197
+ } else {
198
+ console.log(
199
+ `Client has sent binary:` + data.byteLength + " bytes."
200
+ );
201
+ //console.log(data.toString());
202
+ signalingClient.receiveReliableBinaryMessage(data);
203
+ }
204
+ });
205
+ ws.on("error", (error) => {
206
+ console.error("Websocket err " + error);
207
+ });
208
+ // handling what to do when clients disconnects from server
209
+ ws.on("close", () => {
210
+ console.log("the client has connected");
211
+ });
212
+ // handling client connection error
213
+ ws.onerror = function () {
214
+ console.log("Some Error occurred");
215
+ };
216
+ }
217
+ exports.init = function (webRtcCM,newClientFn) {
218
+ // Creating a new websocket server
219
+ const wss = new WebSocketServer.Server({ port: 8081 });
220
+ webRtcConnectionManager = webRtcCM;
221
+ newClient=newClientFn;
222
+ // Creating connection using websocket
223
+ wss.on("connection", (ws, req) => {
224
+ OnWebSocket(ws, req);
225
+ });
226
+ console.log("The WebSockets Signaling Server is running on port " + wss.options.port);
227
+ };
228
+ exports.sendConfigMessage = function (clientID, msg) {
229
+ // Test: is this message valid json?
230
+ var escapedStr=msg.toString();
231
+ try{
232
+ escapedStr=escapedStr.replaceAll('\r','\\r');
233
+ escapedStr=escapedStr.replaceAll('\n','\\n');
234
+ var message = JSON.parse(escapedStr);
235
+ } catch(error)
236
+ {
237
+ console.error(error);
238
+ console.error("Invalid json: "+escapedStr);
239
+ return;
240
+ }
241
+
242
+
243
+ if (signalingClients.has(clientID)) {
244
+ console.log("sendConfigMessage to "+clientID+": "+msg);
245
+ signalingClients[clientID].ws.send(escapedStr);
246
+ } else {
247
+ console.log(
248
+ "sendConfigMessage with clientID " +
249
+ clientID +
250
+ " not in signalingClients map."
251
+ );
252
+ }
253
+ };
254
+
255
+ exports.signalingClients = signalingClients;
package/temp.js ADDED
@@ -0,0 +1 @@
1
+ Hello World!
package/test.json ADDED
@@ -0,0 +1,2 @@
1
+
2
+ {"sdp":"v=0\r\no=rtc 3209902504 0 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0\r\na=msid-semantic:WMS *\r\na=setup:actpass\r\na=ice-ufrag:Ef8E\r\na=ice-pwd:vRnYVyM/w7vvHO5j2vW+Pq\r\na=ice-options:ice2,trickle\r\na=fingerprint:sha-256 1F:D4:D3:39:23:F8:C6:C1:25:29:71:BE:A3:99:58:D6:7D:CA:A9:2A:95:FE:99:59:92:52:7E:2F:2F:42:63:C1\r\nm=application 9 UDP/DTLS/SCTP webrtc-datachannel\r\nc=IN IP4 0.0.0.0\r\na=mid:0\r\na=sendrecv\r\na=sctp-port:5000\r\na=max-message-size:262144\r\n","teleport-signal-type":"offer"}