podasync-ws-only 2.7.11 → 2.8.1-snapshot.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "podasync-ws-only",
3
- "version": "2.7.11",
3
+ "version": "2.8.1-snapshot.0",
4
4
  "description": "Fanap's POD Async service (DIRANA) - Websocket only",
5
5
  "main": "./src/network/async.js",
6
6
  "scripts": {
@@ -8,7 +8,7 @@
8
8
  "publish:snapshot": "npm run version:snapshot && npm publish --tag snapshot",
9
9
  "version:snapshot": "npm version prerelease --preid snapshot",
10
10
  "publish:release": "npm run version:release && npm publish",
11
- "version:release": "npm version 2.7.11"
11
+ "version:release": "npm version 2.8.0"
12
12
  },
13
13
  "repository": {
14
14
  "type": "git",
@@ -13,10 +13,12 @@
13
13
  *******************************************************/
14
14
 
15
15
  var PodSocketClass,
16
+ WebRTCClass,
16
17
  PodUtility,
17
18
  LogLevel
18
19
  if (typeof(require) !== 'undefined' && typeof(exports) !== 'undefined') {
19
20
  PodSocketClass = require('./socket.js');
21
+ WebRTCClass = require('./webrtc.js');
20
22
  PodUtility = require('../utility/utility.js');
21
23
  LogLevel = require('../utility/logger.js');
22
24
  }
@@ -42,6 +44,7 @@
42
44
  },
43
45
  ackCallback = {},
44
46
  socket,
47
+ webRTCClass,
45
48
  asyncMessageType = {
46
49
  PING: 0,
47
50
  SERVER_REGISTER: 1,
@@ -90,7 +93,8 @@
90
93
  ? params.asyncLogging.onMessageReceive
91
94
  : false,
92
95
  onSendLogging = (params.asyncLogging && typeof params.asyncLogging.onMessageSend === 'boolean') ? params.asyncLogging.onMessageSend : false,
93
- workerId = (params.asyncLogging && typeof parseInt(params.asyncLogging.workerId) === 'number') ? params.asyncLogging.workerId : 0;
96
+ workerId = (params.asyncLogging && typeof parseInt(params.asyncLogging.workerId) === 'number') ? params.asyncLogging.workerId : 0,
97
+ webrtcConfig = (params.webrtcConfig ? params.webrtcConfig : null);
94
98
 
95
99
  // function setRetryStep(val){
96
100
  // console.log("new retryStep value:", val);
@@ -121,6 +125,9 @@
121
125
  case 'websocket':
122
126
  initSocket();
123
127
  break;
128
+ case 'webrtc':
129
+ initWebrtc();
130
+ break;
124
131
  }
125
132
  },
126
133
 
@@ -288,6 +295,124 @@
288
295
  });
289
296
  });
290
297
  },
298
+ initWebrtc = function () {
299
+ webRTCClass = new WebRTCClass({
300
+ baseUrl: (webrtcConfig ? webrtcConfig.baseUrl : null),
301
+ configuration : (webrtcConfig ? webrtcConfig.configuration : null),
302
+ connectionCheckTimeout: params.connectionCheckTimeout,
303
+ logLevel: logLevel
304
+ });
305
+
306
+ checkIfSocketHasOpennedTimeoutId = setTimeout(function () {
307
+ if (!isSocketOpen) {
308
+ fireEvent('error', {
309
+ errorCode: 4001,
310
+ errorMessage: 'Can not open Socket!'
311
+ });
312
+ }
313
+ }, 65000);
314
+
315
+ webRTCClass.on('open', function () {
316
+ checkIfSocketHasOpennedTimeoutId && clearTimeout(checkIfSocketHasOpennedTimeoutId);
317
+ socketReconnectRetryInterval && clearTimeout(socketReconnectRetryInterval);
318
+ socketReconnectCheck && clearTimeout(socketReconnectCheck);
319
+
320
+ isSocketOpen = true;
321
+ retryStep.set(4);
322
+
323
+ socketState = socketStateType.OPEN;
324
+ fireEvent('stateChange', {
325
+ socketState: socketState,
326
+ timeUntilReconnect: 0,
327
+ deviceRegister: isDeviceRegister,
328
+ serverRegister: isServerRegister,
329
+ peerId: peerId
330
+ });
331
+ });
332
+
333
+ webRTCClass.on('message', function (msg) {
334
+ console.log({msg})
335
+ handleSocketMessage(msg);
336
+ if (onReceiveLogging) {
337
+ asyncLogger('Receive', msg);
338
+ }
339
+ });
340
+
341
+ webRTCClass.on('close', function (event) {
342
+ isSocketOpen = false;
343
+ isDeviceRegister = false;
344
+ oldPeerId = peerId;
345
+
346
+ fireEvent('disconnect', event);
347
+
348
+ if (reconnectOnClose) {
349
+ if (asyncLogging) {
350
+ if (workerId > 0) {
351
+ Utility.asyncStepLogger(workerId + '\t Reconnecting after ' + retryStep.get() + 's');
352
+ }
353
+ else {
354
+ Utility.asyncStepLogger('Reconnecting after ' + retryStep.get() + 's');
355
+ }
356
+ }
357
+
358
+ logLevel.debug && console.debug("[Async][async.js] on connection close, retryStep:", retryStep.get());
359
+
360
+ socketState = socketStateType.CLOSED;
361
+ fireEvent('stateChange', {
362
+ socketState: socketState,
363
+ timeUntilReconnect: 1000 * retryStep.get(),
364
+ deviceRegister: isDeviceRegister,
365
+ serverRegister: isServerRegister,
366
+ peerId: peerId
367
+ });
368
+
369
+ socketReconnectRetryInterval && clearTimeout(socketReconnectRetryInterval);
370
+
371
+ socketReconnectRetryInterval = setTimeout(function () {
372
+ webRTCClass.connect();
373
+ }, 1000 * retryStep.get());
374
+
375
+ if (retryStep.get() < 64) {
376
+ // retryStep += 3;
377
+ retryStep.set(retryStep.get() + 3)
378
+ }
379
+ }
380
+ else {
381
+ socketReconnectRetryInterval && clearTimeout(socketReconnectRetryInterval);
382
+ socketReconnectCheck && clearTimeout(socketReconnectCheck);
383
+ fireEvent('error', {
384
+ errorCode: 4005,
385
+ errorMessage: 'Connection Closed!'
386
+ });
387
+
388
+ socketState = socketStateType.CLOSED;
389
+ fireEvent('stateChange', {
390
+ socketState: socketState,
391
+ timeUntilReconnect: 0,
392
+ deviceRegister: isDeviceRegister,
393
+ serverRegister: isServerRegister,
394
+ peerId: peerId
395
+ });
396
+ }
397
+
398
+ });
399
+
400
+ webRTCClass.on('customError', function (error) {
401
+ fireEvent('error', {
402
+ errorCode: error.errorCode,
403
+ errorMessage: error.errorMessage,
404
+ errorEvent: error.errorEvent
405
+ });
406
+ });
407
+
408
+ webRTCClass.on('error', function (error) {
409
+ fireEvent('error', {
410
+ errorCode: '',
411
+ errorMessage: '',
412
+ errorEvent: error
413
+ });
414
+ });
415
+ },
291
416
 
292
417
  handleSocketMessage = function (msg) {
293
418
  var ack;
@@ -538,6 +663,15 @@
538
663
  else {
539
664
  pushSendDataQueue.push(msg);
540
665
  }
666
+ break;
667
+ case 'webrtc':
668
+ if (socketState === socketStateType.OPEN) {
669
+ webRTCClass.emit(msg);
670
+ }
671
+ else {
672
+ pushSendDataQueue.push(msg);
673
+ }
674
+
541
675
  break;
542
676
  }
543
677
  },
@@ -558,16 +692,16 @@
558
692
 
559
693
  fireEvent = function (eventName, param, ack) {
560
694
  // try {
561
- if (ack) {
562
- for (var id in eventCallbacks[eventName]) {
563
- eventCallbacks[eventName][id](param, ack);
564
- }
695
+ if (ack) {
696
+ for (var id in eventCallbacks[eventName]) {
697
+ eventCallbacks[eventName][id](param, ack);
565
698
  }
566
- else {
567
- for (var id in eventCallbacks[eventName]) {
568
- eventCallbacks[eventName][id](param);
569
- }
699
+ }
700
+ else {
701
+ for (var id in eventCallbacks[eventName]) {
702
+ eventCallbacks[eventName][id](param);
570
703
  }
704
+ }
571
705
  // }
572
706
  // catch (e) {
573
707
  // fireEvent('error', {
@@ -668,6 +802,20 @@
668
802
 
669
803
  socketReconnectRetryInterval && clearTimeout(socketReconnectRetryInterval);
670
804
  socket.close();
805
+ break;
806
+ case 'webrtc':
807
+ socketState = socketStateType.CLOSED;
808
+ fireEvent('stateChange', {
809
+ socketState: socketState,
810
+ timeUntilReconnect: 0,
811
+ deviceRegister: isDeviceRegister,
812
+ serverRegister: isServerRegister,
813
+ peerId: peerId
814
+ });
815
+
816
+ socketReconnectRetryInterval && clearTimeout(socketReconnectRetryInterval);
817
+ webRTCClass.close();
818
+
671
819
  break;
672
820
  }
673
821
  };
@@ -697,6 +845,20 @@
697
845
  reconnectOnClose = false;
698
846
 
699
847
  socket.close();
848
+ break;
849
+ case 'webrtc':
850
+ socketState = socketStateType.CLOSED;
851
+ fireEvent('stateChange', {
852
+ socketState: socketState,
853
+ timeUntilReconnect: 0,
854
+ deviceRegister: isDeviceRegister,
855
+ serverRegister: isServerRegister,
856
+ peerId: peerId
857
+ });
858
+
859
+ reconnectOnClose = false;
860
+ webRTCClass.close();
861
+
700
862
  break;
701
863
  }
702
864
  };
@@ -717,12 +879,18 @@
717
879
  });
718
880
 
719
881
  socketReconnectRetryInterval && clearTimeout(socketReconnectRetryInterval);
720
- socket.close();
882
+ if(protocol === "websocket")
883
+ socket.close();
884
+ else if(protocol == "webrtc")
885
+ webRTCClass.close()
721
886
 
722
887
  socketReconnectRetryInterval = setTimeout(function () {
723
888
  // retryStep = 4;
724
889
  retryStep.set(4);
725
- socket.connect();
890
+ if(protocol === "websocket")
891
+ socket.close();
892
+ else if(protocol == "webrtc")
893
+ webRTCClass.close()
726
894
  }, 2000);
727
895
  };
728
896
 
@@ -17,15 +17,15 @@
17
17
  *******************************************************/
18
18
 
19
19
  var address = params.socketAddress,
20
- wsConnectionWaitTime = params.wsConnectionWaitTime || 500,
21
- connectionCheckTimeout = params.connectionCheckTimeout || 10000,
22
- eventCallback = {},
23
- socket,
24
- waitForSocketToConnectTimeoutId,
25
- socketRealTimeStatusInterval,
26
- logLevel = params.logLevel,
27
- pingController = new PingManager({waitTime: connectionCheckTimeout}),
28
- socketWatchTimeout;
20
+ wsConnectionWaitTime = params.wsConnectionWaitTime || 500,
21
+ connectionCheckTimeout = params.connectionCheckTimeout || 10000,
22
+ eventCallback = {},
23
+ socket,
24
+ waitForSocketToConnectTimeoutId,
25
+ socketRealTimeStatusInterval,
26
+ logLevel = params.logLevel,
27
+ pingController = new PingManager({waitTime: connectionCheckTimeout}),
28
+ socketWatchTimeout;
29
29
 
30
30
 
31
31
  function PingManager(params) {
@@ -39,7 +39,7 @@
39
39
  first: null,
40
40
  second: null,
41
41
  third: null,
42
- fourth: null
42
+ //fourth: null
43
43
  }
44
44
  }
45
45
 
@@ -51,13 +51,13 @@
51
51
  setPingTimeout() {
52
52
  config.timeoutIds.first = setTimeout(()=>{
53
53
  ping();
54
- config.timeoutIds.first = setTimeout(()=>{
54
+ config.timeoutIds.second = setTimeout(()=>{
55
55
  ping();
56
- config.timeoutIds.fourth = setTimeout(()=>{
57
- logLevel.debug && console.debug("[Async][Socket.js] Force closing socket.");
58
- onCloseHandler(null);
59
- socket.close();
60
- }, 2000);
56
+ config.timeoutIds.third = setTimeout(()=>{
57
+ logLevel.debug && console.debug("[Async][Socket.js] Force closing socket.");
58
+ onCloseHandler(null);
59
+ socket.close();
60
+ }, 2000);
61
61
  }, 2000);
62
62
  }, 8000);
63
63
  },
@@ -65,7 +65,7 @@
65
65
  clearTimeout(config.timeoutIds.first);
66
66
  clearTimeout(config.timeoutIds.second);
67
67
  clearTimeout(config.timeoutIds.third);
68
- clearTimeout(config.timeoutIds.fourth);
68
+ // clearTimeout(config.timeoutIds.fourth);
69
69
  },
70
70
  }
71
71
  }
@@ -75,135 +75,135 @@
75
75
  *******************************************************/
76
76
 
77
77
  var init = function() {
78
- connect();
79
- },
78
+ connect();
79
+ },
80
80
 
81
- connect = function() {
82
- try {
83
- if (socket && socket.readyState == 1) {
84
- return;
85
- }
81
+ connect = function() {
82
+ try {
83
+ if (socket && socket.readyState == 1) {
84
+ return;
85
+ }
86
+
87
+ socket = new WebSocket(address, []);
88
+
89
+ // socketRealTimeStatusInterval && clearInterval(socketRealTimeStatusInterval);
90
+ // socketRealTimeStatusInterval = setInterval(function() {
91
+ // switch (socket.readyState) {
92
+ // case 2:
93
+ // onCloseHandler(null);
94
+ // socketRealTimeStatusInterval && clearInterval(socketRealTimeStatusInterval);
95
+ // break;
96
+ // case 3:
97
+ //
98
+ // break;
99
+ // }
100
+ // }, 5000);
101
+
102
+ /**
103
+ * Watches the socket to make sure it's state changes to 1 in 5 seconds
104
+ */
105
+ socketWatchTimeout && clearTimeout(socketWatchTimeout);
106
+ socketWatchTimeout = setTimeout(() => {
107
+ // if(socket.readyState !== 1) {
108
+ logLevel.debug && console.debug("[Async][Socket.js] socketWatchTimeout triggered.");
109
+ onCloseHandler(null);
110
+ socket.close();
111
+ // }
112
+ }, 5000);
113
+
114
+ socket.onopen = function(event) {
115
+ waitForSocketToConnect(function() {
116
+ pingController.resetPingLoop();
117
+ eventCallback["open"]();
118
+ socketWatchTimeout && clearTimeout(socketWatchTimeout);
119
+ });
120
+ }
86
121
 
87
- socket = new WebSocket(address, []);
88
-
89
- // socketRealTimeStatusInterval && clearInterval(socketRealTimeStatusInterval);
90
- // socketRealTimeStatusInterval = setInterval(function() {
91
- // switch (socket.readyState) {
92
- // case 2:
93
- // onCloseHandler(null);
94
- // socketRealTimeStatusInterval && clearInterval(socketRealTimeStatusInterval);
95
- // break;
96
- // case 3:
97
- //
98
- // break;
99
- // }
100
- // }, 5000);
101
-
102
- /**
103
- * Watches the socket to make sure it's state changes to 1 in 5 seconds
104
- */
105
- socketWatchTimeout && clearTimeout(socketWatchTimeout);
106
- socketWatchTimeout = setTimeout(() => {
107
- // if(socket.readyState !== 1) {
108
- logLevel.debug && console.debug("[Async][Socket.js] socketWatchTimeout triggered.");
109
- onCloseHandler(null);
110
- socket.close();
111
- // }
112
- }, 5000);
113
-
114
- socket.onopen = function(event) {
115
- waitForSocketToConnect(function() {
122
+ socket.onmessage = function(event) {
116
123
  pingController.resetPingLoop();
117
- eventCallback["open"]();
124
+
125
+ var messageData = JSON.parse(event.data);
126
+ eventCallback["message"](messageData);
127
+ }
128
+
129
+ socket.onclose = function(event) {
130
+ pingController.stopPingLoop();
131
+ logLevel.debug && console.debug("[Async][Socket.js] socket.onclose happened. EventData:", event);
132
+ onCloseHandler(event);
133
+ socketWatchTimeout && clearTimeout(socketWatchTimeout);
134
+ }
135
+
136
+ socket.onerror = function(event) {
137
+ logLevel.debug && console.debug("[Async][Socket.js] socket.onerror happened. EventData:", event);
138
+ eventCallback["error"](event);
118
139
  socketWatchTimeout && clearTimeout(socketWatchTimeout);
140
+ }
141
+ } catch (error) {
142
+ eventCallback["customError"]({
143
+ errorCode: 4000,
144
+ errorMessage: "ERROR in WEBSOCKET!",
145
+ errorEvent: error
119
146
  });
120
147
  }
148
+ },
121
149
 
122
- socket.onmessage = function(event) {
123
- pingController.resetPingLoop();
150
+ onCloseHandler = function(event) {
151
+ pingController.stopPingLoop();
152
+ socket.onclose = null;
153
+ socket.onmessage = null;
154
+ socket.onerror = null;
155
+ socket.onopen = null;
156
+ eventCallback["close"](event);
157
+ },
124
158
 
125
- var messageData = JSON.parse(event.data);
126
- eventCallback["message"](messageData);
127
- }
159
+ ping = function() {
160
+ sendData({
161
+ type: 0
162
+ });
163
+ },
128
164
 
129
- socket.onclose = function(event) {
130
- pingController.stopPingLoop();
131
- logLevel.debug && console.debug("[Async][Socket.js] socket.onclose happened. EventData:", event);
132
- onCloseHandler(event);
133
- socketWatchTimeout && clearTimeout(socketWatchTimeout);
134
- }
165
+ waitForSocketToConnect = function(callback) {
166
+ waitForSocketToConnectTimeoutId && clearTimeout(waitForSocketToConnectTimeoutId);
135
167
 
136
- socket.onerror = function(event) {
137
- logLevel.debug && console.debug("[Async][Socket.js] socket.onerror happened. EventData:", event);
138
- eventCallback["error"](event);
139
- socketWatchTimeout && clearTimeout(socketWatchTimeout);
168
+ if (socket.readyState === 1) {
169
+ callback();
170
+ } else {
171
+ waitForSocketToConnectTimeoutId = setTimeout(function() {
172
+ if (socket.readyState === 1) {
173
+ callback();
174
+ } else {
175
+ waitForSocketToConnect(callback);
176
+ }
177
+ }, wsConnectionWaitTime);
140
178
  }
141
- } catch (error) {
142
- eventCallback["customError"]({
143
- errorCode: 4000,
144
- errorMessage: "ERROR in WEBSOCKET!",
145
- errorEvent: error
146
- });
147
- }
148
- },
149
-
150
- onCloseHandler = function(event) {
151
- pingController.stopPingLoop();
152
- socket.onclose = null;
153
- socket.onmessage = null;
154
- socket.onerror = null;
155
- socket.onopen = null;
156
- eventCallback["close"](event);
157
- },
158
-
159
- ping = function() {
160
- sendData({
161
- type: 0
162
- });
163
- },
164
-
165
- waitForSocketToConnect = function(callback) {
166
- waitForSocketToConnectTimeoutId && clearTimeout(waitForSocketToConnectTimeoutId);
167
-
168
- if (socket.readyState === 1) {
169
- callback();
170
- } else {
171
- waitForSocketToConnectTimeoutId = setTimeout(function() {
172
- if (socket.readyState === 1) {
173
- callback();
174
- } else {
175
- waitForSocketToConnect(callback);
176
- }
177
- }, wsConnectionWaitTime);
178
- }
179
- },
180
-
181
- sendData = function(params) {
182
- var data = {
183
- type: params.type,
184
- uniqueId: params.uniqueId
185
- };
179
+ },
186
180
 
187
- if (params.trackerId) {
188
- data.trackerId = params.trackerId;
189
- }
181
+ sendData = function(params) {
182
+ var data = {
183
+ type: params.type,
184
+ uniqueId: params.uniqueId
185
+ };
190
186
 
191
- try {
192
- if (params.content) {
193
- data.content = JSON.stringify(params.content);
187
+ if (params.trackerId) {
188
+ data.trackerId = params.trackerId;
194
189
  }
195
190
 
196
- if (socket.readyState === 1) {
197
- socket.send(JSON.stringify(data));
191
+ try {
192
+ if (params.content) {
193
+ data.content = JSON.stringify(params.content);
194
+ }
195
+
196
+ if (socket.readyState === 1) {
197
+ socket.send(JSON.stringify(data));
198
+ }
199
+ } catch (error) {
200
+ eventCallback["customError"]({
201
+ errorCode: 4004,
202
+ errorMessage: "Error in Socket sendData!",
203
+ errorEvent: error
204
+ });
198
205
  }
199
- } catch (error) {
200
- eventCallback["customError"]({
201
- errorCode: 4004,
202
- errorMessage: "Error in Socket sendData!",
203
- errorEvent: error
204
- });
205
- }
206
- };
206
+ };
207
207
 
208
208
  /*******************************************************
209
209
  * P U B L I C M E T H O D S *
@@ -0,0 +1,459 @@
1
+ let defaultConfig = {
2
+ baseUrl: "http://109.201.0.97/webrtc/",
3
+ registerEndpoint: "register/",
4
+ addICEEndpoint: "add-ice/",
5
+ getICEEndpoint: "get-ice/?",
6
+ configuration: {
7
+ bundlePolicy: "balanced",
8
+ iceTransportPolicy: "relay",
9
+ iceServers: [{
10
+ "urls": "turn:turnsandbox.podstream.ir:3478", "username": "mkhorrami", "credential": "mkh_123456"
11
+ }]
12
+ },
13
+ connectionCheckTimeout: 10000,
14
+ logLevel: null
15
+ },
16
+ variables = {
17
+ peerConnection: null,
18
+ dataChannel: null,
19
+ pingController: new PingManager({waitTime: defaultConfig.connectionCheckTimeout}),
20
+ candidatesQueue: [],
21
+ // candidatesSendQueue: [],
22
+ candidateManager: new CandidatesSendQueueManager(),
23
+ clientId: null,
24
+ deviceId: null,
25
+ apiCallRetries: {
26
+ register: 3,
27
+ getIce: 3,
28
+ addIce: 5
29
+ }
30
+ };
31
+
32
+ function CandidatesSendQueueManager() {
33
+ let config = {
34
+ candidatesToSend: [],
35
+ alreadyReceivedServerCandidates: false,
36
+ reCheckTimeout: null
37
+ }
38
+
39
+ function trySendingCandidates() {
40
+ timoutCallback();
41
+ function timoutCallback() {
42
+ if(variables.peerConnection.signalingState === 'stable') {
43
+ config.reCheckTimeout && clearTimeout(config.reCheckTimeout);
44
+ if (config.candidatesToSend.length) {
45
+ let entry = config.candidatesToSend.shift();
46
+ handshakingFunctions
47
+ .sendCandidate(entry)
48
+ .then(function (result) {
49
+ if (result.length) {
50
+ addServerCandidates(result);
51
+
52
+ config.alreadyReceivedServerCandidates = true;
53
+ }
54
+ trySendingCandidates();
55
+ });
56
+
57
+ } else if (!config.alreadyReceivedServerCandidates) {
58
+ handshakingFunctions.getCandidates(variables.clientId).then(function (result) {
59
+ addServerCandidates(result)
60
+ }).catch();
61
+ }
62
+ } else {
63
+ config.reCheckTimeout && clearTimeout(config.reCheckTimeout);
64
+ config.reCheckTimeout = setTimeout(timoutCallback, 1000);
65
+ }
66
+ }
67
+ }
68
+
69
+ function addServerCandidates(candidates) {
70
+ for(let i in candidates) {
71
+ webrtcFunctions.putCandidateToQueue(candidates[i]);
72
+ }
73
+ }
74
+
75
+ return {
76
+ add: function (candidate) {
77
+ config.candidatesToSend.push(candidate);
78
+ trySendingCandidates();
79
+ },
80
+ destroy: function (){
81
+ config.reCheckTimeout && clearTimeout(config.reCheckTimeout);
82
+ }
83
+ }
84
+ }
85
+
86
+ function PingManager(params) {
87
+ const config = {
88
+ normalWaitTime: params.waitTime,
89
+
90
+ lastRequestTimeoutId: null,
91
+ lastReceivedMessageTime: 0,
92
+ totalNoMessageCount: 0,
93
+ timeoutIds: {
94
+ first: null,
95
+ second: null,
96
+ third: null,
97
+ fourth: null
98
+ }
99
+ }
100
+
101
+ return {
102
+ resetPingLoop() {
103
+ this.stopPingLoop();
104
+ this.setPingTimeout();
105
+ },
106
+ setPingTimeout() {
107
+ config.timeoutIds.first = setTimeout(() => {
108
+ ping();
109
+ config.timeoutIds.second = setTimeout(() => {
110
+ ping();
111
+ config.timeoutIds.third = setTimeout(() => {
112
+ defaultConfig.logLevel.debug && console.debug("[Async][Webrtc.js] Force closing connection.");
113
+ publicized.close();
114
+ }, 2000);
115
+ }, 2000);
116
+ }, 8000);
117
+ },
118
+ stopPingLoop() {
119
+ clearTimeout(config.timeoutIds.first);
120
+ clearTimeout(config.timeoutIds.second);
121
+ clearTimeout(config.timeoutIds.third);
122
+ // clearTimeout(config.timeoutIds.fourth);
123
+ },
124
+ }
125
+ }
126
+
127
+ function connect() {
128
+ webrtcFunctions.createPeerConnection();
129
+ webrtcFunctions.createDataChannel();
130
+ webrtcFunctions.generateSdpOffer()
131
+ .then(sendOfferToServer);
132
+
133
+ function sendOfferToServer(offer) {
134
+ handshakingFunctions
135
+ .register(offer.sdp)
136
+ .then(processRegisterResult).catch();
137
+
138
+ variables
139
+ .peerConnection.setLocalDescription(offer)
140
+ .catch(error => console.error(error));
141
+ }
142
+
143
+ function processRegisterResult(result) {
144
+ variables.clientId = result.clientId;
145
+ variables.deviceId = result.deviceId;
146
+ webrtcFunctions.processAnswer(result.sdpAnswer);
147
+ }
148
+ }
149
+
150
+ let webrtcFunctions = {
151
+ createPeerConnection: function () {
152
+ variables.peerConnection = new RTCPeerConnection(defaultConfig.configuration);
153
+ variables.peerConnection.addEventListener('signalingstatechange', webrtcFunctions.signalingStateChangeCallback);
154
+ variables.peerConnection.onicecandidate = function (event) {
155
+ if (event.candidate) {
156
+ variables.candidateManager.add(event.candidate);
157
+ webrtcFunctions.putCandidateToQueue(event.candidate);
158
+ }
159
+ };
160
+ },
161
+ signalingStateChangeCallback: function () {
162
+ if (variables.peerConnection.signalingState === 'stable') {
163
+ // handshakingFunctions.getCandidates().catch()
164
+ webrtcFunctions.addTheCandidates();
165
+ }
166
+ },
167
+ createDataChannel: function () {
168
+ variables.dataChannel = variables.peerConnection.createDataChannel("dataChannel", {ordered: false});
169
+ variables.dataChannel.onopen = dataChannelCallbacks.onopen;
170
+ variables.dataChannel.onmessage = dataChannelCallbacks.onmessage;
171
+ variables.dataChannel.onerror = dataChannelCallbacks.onerror;
172
+ variables.dataChannel.onclose = dataChannelCallbacks.onclose;
173
+ },
174
+ generateSdpOffer: function () {
175
+ return new Promise(function (resolve, reject) {
176
+ variables.peerConnection.createOffer(function (offer) {
177
+ resolve(offer)
178
+ }, function (error) {
179
+ reject(error);
180
+ console.error(error);
181
+ }).then(r => console.log(r));
182
+ })
183
+ },
184
+ processAnswer: function (answer) {
185
+ let remoteDesc = {
186
+ type: "answer", sdp: answer
187
+ };
188
+ variables
189
+ .peerConnection
190
+ .setRemoteDescription(new RTCSessionDescription(remoteDesc))
191
+ .catch(function (error) {
192
+ console.error(error)
193
+ });
194
+ },
195
+ addTheCandidates: function () {
196
+ while (variables.candidatesQueue.length) {
197
+ let entry = variables.candidatesQueue.shift();
198
+ variables.peerConnection.addIceCandidate(entry.candidate);
199
+ }
200
+ },
201
+ putCandidateToQueue: function (candidate) {
202
+ variables.candidatesQueue.push({
203
+ candidate: new RTCIceCandidate(candidate)
204
+ });
205
+ if (variables.peerConnection.signalingState === 'stable') {
206
+ webrtcFunctions.addTheCandidates();
207
+ }
208
+ },
209
+ sendData: function(params) {
210
+ if(!variables.dataChannel) {
211
+ console.error("Connection is closed, do not send messages.")
212
+ return;
213
+ }
214
+ var data = {
215
+ type: params.type,
216
+ uniqueId: params.uniqueId
217
+ };
218
+
219
+ if (params.trackerId) {
220
+ data.trackerId = params.trackerId;
221
+ }
222
+
223
+ try {
224
+ if (params.content) {
225
+ data.content = JSON.stringify(params.content);
226
+ }
227
+
228
+ if (variables.peerConnection.signalingState === 'stable') {
229
+ //defaultConfig.logLevel.debug &&
230
+ console.log("[Async][WebRTC] Send ", data);
231
+ variables.dataChannel.send(JSON.stringify(data));
232
+ }
233
+ } catch (error) {
234
+ eventCallback["customError"]({
235
+ errorCode: 4004,
236
+ errorMessage: "Error in Socket sendData!",
237
+ errorEvent: error
238
+ });
239
+ }
240
+ }
241
+ }
242
+
243
+ let dataChannelCallbacks = {
244
+ onopen: function (event) {
245
+ console.log("********* dataChannel open *********");
246
+ variables.pingController.resetPingLoop();
247
+ eventCallback["open"]();
248
+
249
+ const deviceRegister = {
250
+ "type": "2",
251
+ "content": {"deviceId": variables.deviceId, "appId": "PodChat", "refresh": false, "renew": true}
252
+ };
253
+ deviceRegister.content = JSON.stringify(deviceRegister.content)
254
+ variables.dataChannel.send(JSON.stringify(deviceRegister));
255
+ },
256
+
257
+ onmessage: function (event) {
258
+
259
+ variables.pingController.resetPingLoop();
260
+ var messageData = JSON.parse(event.data);
261
+ console.log("[Async][WebRTC] Receive ", event.data);
262
+ eventCallback["message"](messageData);
263
+ },
264
+
265
+ onerror: function (error) {
266
+ logLevel.debug && console.debug("[Async][Socket.js] dataChannel.onerror happened. EventData:", event);
267
+ eventCallback["error"](event);
268
+ },
269
+ onclose: function (event) {
270
+ resetVariables();
271
+ eventCallback["close"](event);
272
+ }
273
+ }
274
+
275
+ let handshakingFunctions = {
276
+ register: function (offer) {
277
+ let retries = variables.apiCallRetries.register;
278
+ return new Promise(promiseHandler);
279
+ function promiseHandler(resolve, reject) {
280
+ let registerEndPoint = defaultConfig.baseUrl + defaultConfig.registerEndpoint
281
+ fetch(registerEndPoint, {
282
+ method: "POST",
283
+ body: JSON.stringify({
284
+ offer: offer
285
+ })
286
+ })
287
+ .then(function (response) {
288
+ if(response.ok)
289
+ return response.json();
290
+ else if(retries){
291
+ retryTheRequest(resolve, reject);
292
+ retries--;
293
+ } else reject();
294
+ })
295
+ .then(result => resolve(result))
296
+ .catch(err => {
297
+ if(retries){
298
+ retryTheRequest(resolve, reject);
299
+ retries--;
300
+ } else {
301
+ publicized.close();
302
+ }
303
+ console.error(err);
304
+ });
305
+ }
306
+ function retryTheRequest(resolve, reject){
307
+ setTimeout(function (){promiseHandler(resolve, reject)}, 1000);
308
+ }
309
+ },
310
+ getCandidates: function (clientId) {
311
+ let addIceCandidateEndPoint = defaultConfig.baseUrl + defaultConfig.getICEEndpoint
312
+ addIceCandidateEndPoint += "clientId=" + clientId;
313
+
314
+ let retries = variables.apiCallRetries.getIce;
315
+ return new Promise(promiseHandler);
316
+ function promiseHandler(resolve, reject) {
317
+ fetch(addIceCandidateEndPoint, {
318
+ method: "GET"
319
+ })
320
+ .then(function (response) {
321
+ if(response.ok)
322
+ return response.json();
323
+ else if(retries){
324
+ retryTheRequest(resolve, reject);
325
+ retries--;
326
+ } else reject();
327
+ })
328
+ .then(function (result) {
329
+ resolve(result.iceCandidates)
330
+ // if(result.iceCandidates && result.iceCandidates.length) {
331
+ // // result.iceCandidates.forEach((item) => {
332
+ // // webrtcFunctions.putCandidateToQueue(item);
333
+ // // });
334
+ // resolve(result.iceCandidates)
335
+ // }
336
+ // else {
337
+ // if(retries){
338
+ // retryTheRequest(resolve, reject);
339
+ // retries--;
340
+ // } else reject();
341
+ // }
342
+ })
343
+ .catch(function (err) {
344
+ if(retries){
345
+ retryTheRequest(resolve, reject);
346
+ retries--;
347
+ } else reject(err);
348
+ console.error(err);
349
+ });
350
+ }
351
+
352
+ function retryTheRequest(resolve, reject){
353
+ setTimeout(function (){promiseHandler(resolve, reject)}, 1000);
354
+ }
355
+
356
+ },
357
+ sendCandidate: function (candidate) {
358
+ let addIceCandidateEndPoint = defaultConfig.baseUrl + defaultConfig.addICEEndpoint
359
+ , retries = variables.apiCallRetries.addIce;
360
+
361
+ return new Promise(promiseHandler);
362
+ function promiseHandler(resolve, reject) {
363
+ fetch(addIceCandidateEndPoint, {
364
+ method: "POST",
365
+ body: JSON.stringify({
366
+ "clientId": variables.clientId,
367
+ "candidate": candidate
368
+ })
369
+ })
370
+ .then(function (response) {
371
+ if(response.ok)
372
+ return response.json();
373
+ else if(retries){
374
+ retryTheRequest(resolve, reject);
375
+ retries--;
376
+ } else reject();
377
+ })
378
+ .then(function (result) {
379
+ resolve(result.iceCandidates);
380
+ })
381
+ .catch(err => {
382
+ if(retries){
383
+ retryTheRequest(resolve, reject);
384
+ retries--;
385
+ } else reject(err);
386
+ console.error(err);
387
+ });
388
+ }
389
+
390
+ function retryTheRequest(resolve, reject){
391
+ setTimeout(function (){promiseHandler(resolve, reject)}, 2000);
392
+ }
393
+ }
394
+ }
395
+
396
+ eventCallback = {};
397
+
398
+ function resetVariables() {
399
+ console.log("resetVariables");
400
+ eventCallback["close"]();
401
+ variables.pingController.stopPingLoop();
402
+ variables.dataChannel.close();
403
+ variables.dataChannel = null;
404
+ variables.peerConnection.close();
405
+ variables.peerConnection = null;
406
+ variables.candidatesQueue = [];
407
+ variables.clientId = null;
408
+ variables.deviceId = null;
409
+ variables.candidateManager.destroy();
410
+ variables.candidateManager = new CandidatesSendQueueManager()
411
+ }
412
+
413
+ function ping() {
414
+ webrtcFunctions.sendData({
415
+ type: 0
416
+ });
417
+ }
418
+ function removeCallbacks(){
419
+ variables.peerConnection.onicecandidate = null;
420
+ variables.dataChannel.onclose = null;
421
+ variables.dataChannel.onmessage = null;
422
+ variables.dataChannel.onerror = null;
423
+ variables.dataChannel.onopen = null;
424
+ }
425
+
426
+ function WebRTCClass({
427
+ baseUrl,
428
+ configuration,
429
+ connectionCheckTimeout = 10000,
430
+ logLevel
431
+ }) {
432
+ let config = {}
433
+ if (baseUrl)
434
+ config.baseUrl = baseUrl;
435
+ if (configuration)
436
+ config.configuration = configuration;
437
+ if (connectionCheckTimeout)
438
+ config.connectionCheckTimeout = connectionCheckTimeout;
439
+ if (logLevel)
440
+ config.logLevel = logLevel;
441
+
442
+ defaultConfig = Object.assign(defaultConfig, config);
443
+ connect();
444
+ return publicized;
445
+ }
446
+
447
+ let publicized = {
448
+ on: function (messageName, callback) {
449
+ eventCallback[messageName] = callback;
450
+ },
451
+ emit: webrtcFunctions.sendData,
452
+ connect: connect,
453
+ close: function () {
454
+ removeCallbacks();
455
+ resetVariables();
456
+ }
457
+ };
458
+
459
+ module.exports = WebRTCClass;