quickblox 2.23.1-beta.3 → 2.23.1-beta.4
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/__getStats-mediaType-guard-fix-plan.md +340 -0
- package/package.json +4 -1
- package/quickblox.js +92 -75
- package/quickblox.min.js +1 -1
- package/src/modules/webrtc/qbRTCPeerConnection.js +91 -74
- package/src/qbConfig.js +1 -1
- package/.claude/settings.local.json +0 -13
- package/src/plugins/streamManagement.js +0 -235
|
@@ -542,92 +542,106 @@ function _getStats(peer, lastResults, successCallback, errorCallback) {
|
|
|
542
542
|
|
|
543
543
|
peer.getStats(null).then(function (results) {
|
|
544
544
|
results.forEach(function (result) {
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
if (result.bytesReceived && result.type === 'inbound-rtp') {
|
|
548
|
-
item = statistic.remote[result.mediaType];
|
|
549
|
-
item.bitrate = _getBitratePerSecond(result, lastResults, false);
|
|
550
|
-
item.bytesReceived = result.bytesReceived;
|
|
551
|
-
item.packetsReceived = result.packetsReceived;
|
|
552
|
-
item.timestamp = result.timestamp;
|
|
553
|
-
if (result.mediaType === 'video' && result.framerateMean) {
|
|
554
|
-
item.framesPerSecond = Math.round(result.framerateMean * 10) / 10;
|
|
555
|
-
}
|
|
556
|
-
} else if (result.bytesSent && result.type === 'outbound-rtp') {
|
|
557
|
-
item = statistic.local[result.mediaType];
|
|
558
|
-
item.bitrate = _getBitratePerSecond(result, lastResults, true);
|
|
559
|
-
item.bytesSent = result.bytesSent;
|
|
560
|
-
item.packetsSent = result.packetsSent;
|
|
561
|
-
item.timestamp = result.timestamp;
|
|
562
|
-
if (result.mediaType === 'video' && result.framerateMean) {
|
|
563
|
-
item.framesPerSecond = Math.round(result.framerateMean * 10) / 10;
|
|
564
|
-
}
|
|
565
|
-
} else if (result.type === 'local-candidate') {
|
|
566
|
-
item = statistic.local.candidate;
|
|
567
|
-
if (result.candidateType === 'host' && result.mozLocalTransport === 'udp' && result.transport === 'udp') {
|
|
568
|
-
item.protocol = result.transport;
|
|
569
|
-
item.ip = result.ipAddress;
|
|
570
|
-
item.port = result.portNumber;
|
|
571
|
-
} else if (!Helpers.getVersionFirefox()) {
|
|
572
|
-
item.protocol = result.protocol;
|
|
573
|
-
item.ip = result.ip;
|
|
574
|
-
item.port = result.port;
|
|
575
|
-
}
|
|
576
|
-
} else if (result.type === 'remote-candidate') {
|
|
577
|
-
item = statistic.remote.candidate;
|
|
578
|
-
item.protocol = result.protocol || result.transport;
|
|
579
|
-
item.ip = result.ip || result.ipAddress;
|
|
580
|
-
item.port = result.port || result.portNumber;
|
|
581
|
-
} else if (result.type === 'track' && result.kind === 'video' && !Helpers.getVersionFirefox()) {
|
|
582
|
-
if (result.remoteSource) {
|
|
583
|
-
item = statistic.remote.video;
|
|
584
|
-
item.frameHeight = result.frameHeight;
|
|
585
|
-
item.frameWidth = result.frameWidth;
|
|
586
|
-
item.framesPerSecond = _getFramesPerSecond(result, lastResults, false);
|
|
587
|
-
} else {
|
|
588
|
-
item = statistic.local.video;
|
|
589
|
-
item.frameHeight = result.frameHeight;
|
|
590
|
-
item.frameWidth = result.frameWidth;
|
|
591
|
-
item.framesPerSecond = _getFramesPerSecond(result, lastResults, true);
|
|
592
|
-
}
|
|
593
|
-
}
|
|
545
|
+
_applyStatReport(statistic, result, lastResults);
|
|
594
546
|
});
|
|
595
547
|
successCallback(statistic, results);
|
|
596
548
|
}, errorCallback);
|
|
549
|
+
}
|
|
597
550
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
551
|
+
function _applyStatReport(statistic, result, lastResults) {
|
|
552
|
+
var item;
|
|
553
|
+
|
|
554
|
+
if (result.bytesReceived && result.type === 'inbound-rtp') {
|
|
555
|
+
item = statistic.remote[result.mediaType];
|
|
556
|
+
|
|
557
|
+
if (item) {
|
|
558
|
+
item.bitrate = _getBitratePerSecond(result, lastResults, false);
|
|
559
|
+
item.bytesReceived = result.bytesReceived;
|
|
560
|
+
item.packetsReceived = result.packetsReceived;
|
|
561
|
+
item.timestamp = result.timestamp;
|
|
562
|
+
if (result.mediaType === 'video' && result.framerateMean) {
|
|
563
|
+
item.framesPerSecond = Math.round(result.framerateMean * 10) / 10;
|
|
564
|
+
}
|
|
565
|
+
} else {
|
|
566
|
+
Helpers.traceWarning('_getStats: skipping inbound-rtp report with unknown mediaType: ' + result.mediaType);
|
|
567
|
+
}
|
|
568
|
+
} else if (result.bytesSent && result.type === 'outbound-rtp') {
|
|
569
|
+
item = statistic.local[result.mediaType];
|
|
570
|
+
|
|
571
|
+
if (item) {
|
|
572
|
+
item.bitrate = _getBitratePerSecond(result, lastResults, true);
|
|
573
|
+
item.bytesSent = result.bytesSent;
|
|
574
|
+
item.packetsSent = result.packetsSent;
|
|
575
|
+
item.timestamp = result.timestamp;
|
|
576
|
+
if (result.mediaType === 'video' && result.framerateMean) {
|
|
577
|
+
item.framesPerSecond = Math.round(result.framerateMean * 10) / 10;
|
|
578
|
+
}
|
|
609
579
|
} else {
|
|
610
|
-
|
|
580
|
+
Helpers.traceWarning('_getStats: skipping outbound-rtp report with unknown mediaType: ' + result.mediaType);
|
|
611
581
|
}
|
|
582
|
+
} else if (result.type === 'local-candidate') {
|
|
583
|
+
item = statistic.local.candidate;
|
|
584
|
+
if (result.candidateType === 'host' && result.mozLocalTransport === 'udp' && result.transport === 'udp') {
|
|
585
|
+
item.protocol = result.transport;
|
|
586
|
+
item.ip = result.ipAddress;
|
|
587
|
+
item.port = result.portNumber;
|
|
588
|
+
} else if (!Helpers.getVersionFirefox()) {
|
|
589
|
+
item.protocol = result.protocol;
|
|
590
|
+
item.ip = result.ip;
|
|
591
|
+
item.port = result.port;
|
|
592
|
+
}
|
|
593
|
+
} else if (result.type === 'remote-candidate') {
|
|
594
|
+
item = statistic.remote.candidate;
|
|
595
|
+
item.protocol = result.protocol || result.transport;
|
|
596
|
+
item.ip = result.ip || result.ipAddress;
|
|
597
|
+
item.port = result.port || result.portNumber;
|
|
598
|
+
} else if (result.type === 'track' && result.kind === 'video' && !Helpers.getVersionFirefox()) {
|
|
599
|
+
if (result.remoteSource) {
|
|
600
|
+
item = statistic.remote.video;
|
|
601
|
+
item.frameHeight = result.frameHeight;
|
|
602
|
+
item.frameWidth = result.frameWidth;
|
|
603
|
+
item.framesPerSecond = _getFramesPerSecond(result, lastResults, false);
|
|
604
|
+
} else {
|
|
605
|
+
item = statistic.local.video;
|
|
606
|
+
item.frameHeight = result.frameHeight;
|
|
607
|
+
item.frameWidth = result.frameWidth;
|
|
608
|
+
item.framesPerSecond = _getFramesPerSecond(result, lastResults, true);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
612
|
|
|
613
|
-
|
|
613
|
+
function _getBitratePerSecond(result, lastResults, isLocal) {
|
|
614
|
+
var lastResult = lastResults && lastResults.get(result.id),
|
|
615
|
+
seconds = lastResult ? ((result.timestamp - lastResult.timestamp) / 1000) : 5,
|
|
616
|
+
kilo = 1024,
|
|
617
|
+
bit = 8,
|
|
618
|
+
bitrate;
|
|
619
|
+
|
|
620
|
+
if (!lastResult) {
|
|
621
|
+
bitrate = 0;
|
|
622
|
+
} else if (isLocal) {
|
|
623
|
+
bitrate = bit * (result.bytesSent - lastResult.bytesSent) / (kilo * seconds);
|
|
624
|
+
} else {
|
|
625
|
+
bitrate = bit * (result.bytesReceived - lastResult.bytesReceived) / (kilo * seconds);
|
|
614
626
|
}
|
|
615
627
|
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
seconds = lastResult ? ((result.timestamp - lastResult.timestamp) / 1000) : 5,
|
|
619
|
-
framesPerSecond;
|
|
628
|
+
return Math.round(bitrate);
|
|
629
|
+
}
|
|
620
630
|
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
} else {
|
|
626
|
-
framesPerSecond = (result.framesReceived - lastResult.framesReceived) / seconds;
|
|
627
|
-
}
|
|
631
|
+
function _getFramesPerSecond(result, lastResults, isLocal) {
|
|
632
|
+
var lastResult = lastResults && lastResults.get(result.id),
|
|
633
|
+
seconds = lastResult ? ((result.timestamp - lastResult.timestamp) / 1000) : 5,
|
|
634
|
+
framesPerSecond;
|
|
628
635
|
|
|
629
|
-
|
|
636
|
+
if (!lastResult) {
|
|
637
|
+
framesPerSecond = 0;
|
|
638
|
+
} else if (isLocal) {
|
|
639
|
+
framesPerSecond = (result.framesSent - lastResult.framesSent) / seconds;
|
|
640
|
+
} else {
|
|
641
|
+
framesPerSecond = (result.framesReceived - lastResult.framesReceived) / seconds;
|
|
630
642
|
}
|
|
643
|
+
|
|
644
|
+
return Math.round(framesPerSecond * 10) / 10;
|
|
631
645
|
}
|
|
632
646
|
|
|
633
647
|
// Find the line in sdpLines[startLine...endLine - 1] that starts with |prefix|
|
|
@@ -814,4 +828,7 @@ function setMediaBitrate(sdp, media, bitrate) {
|
|
|
814
828
|
return newLines.join('\n');
|
|
815
829
|
}
|
|
816
830
|
|
|
831
|
+
// PRIVATE - exposed for unit tests only, not part of the public SDK contract.
|
|
832
|
+
qbRTCPeerConnection._applyStatReport = _applyStatReport;
|
|
833
|
+
|
|
817
834
|
module.exports = qbRTCPeerConnection;
|
package/src/qbConfig.js
CHANGED
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* QuickBlox JavaScript SDK
|
|
5
|
-
* Chat Stream Management plugin
|
|
6
|
-
* doc: http://xmpp.org/extensions/xep-0198.html
|
|
7
|
-
*
|
|
8
|
-
* To enable this features add to config
|
|
9
|
-
* ```javascript
|
|
10
|
-
* streamManagement: {
|
|
11
|
-
- enable: true
|
|
12
|
-
- }
|
|
13
|
-
* ```
|
|
14
|
-
*
|
|
15
|
-
* Uses listener by QB.chat.onSentMessageCallback
|
|
16
|
-
*
|
|
17
|
-
* ```javascript
|
|
18
|
-
* QB.chat.onSentMessageCallback = function (messageLost, messageSent) {
|
|
19
|
-
* if (messageLost) {
|
|
20
|
-
* console.error('sendErrorCallback', messageLost);
|
|
21
|
-
* } else {
|
|
22
|
-
* console.info('sendMessageSuccessCallback', messageSent);
|
|
23
|
-
* }
|
|
24
|
-
* };
|
|
25
|
-
* ```
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
/** JSHint inline rules */
|
|
29
|
-
/* globals $build */
|
|
30
|
-
|
|
31
|
-
var Utils = require('../qbUtils'),
|
|
32
|
-
chatUtils = require('../modules/chat/qbChatHelpers');
|
|
33
|
-
|
|
34
|
-
function StreamManagement(options) {
|
|
35
|
-
|
|
36
|
-
this._NS = 'urn:xmpp:sm:3';
|
|
37
|
-
|
|
38
|
-
this._isStreamManagementEnabled = false;
|
|
39
|
-
|
|
40
|
-
// Counter of the incoming stanzas
|
|
41
|
-
this._clientProcessedStanzasCounter = null;
|
|
42
|
-
|
|
43
|
-
// The client send stanza counter.
|
|
44
|
-
this._clientSentStanzasCounter = null;
|
|
45
|
-
|
|
46
|
-
this._intervalId = null;
|
|
47
|
-
|
|
48
|
-
this._timeInterval = Utils.getTimeIntervalForCallBackMessage();
|
|
49
|
-
|
|
50
|
-
this.sentMessageCallback = null;
|
|
51
|
-
|
|
52
|
-
if(Utils.getEnv().browser){
|
|
53
|
-
this._parser = new DOMParser();
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// connection
|
|
57
|
-
this._c = null;
|
|
58
|
-
|
|
59
|
-
this._nodeBuilder = null;
|
|
60
|
-
// Original connection.send method
|
|
61
|
-
this._originalSend = null;
|
|
62
|
-
|
|
63
|
-
// In progress stanzas queue
|
|
64
|
-
this._stanzasQueue = [];
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
StreamManagement.prototype.enable = function (connection, client) {
|
|
69
|
-
var self = this,
|
|
70
|
-
stanza,
|
|
71
|
-
enableParams = {
|
|
72
|
-
xmlns: self._NS
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
if(!self._isStreamManagementEnabled){
|
|
76
|
-
self._c = connection;
|
|
77
|
-
self._originalSend = this._c.send;
|
|
78
|
-
self._c.send = this.send.bind(self);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if(Utils.getEnv().browser){
|
|
82
|
-
this._clientProcessedStanzasCounter = null;
|
|
83
|
-
this._clientSentStanzasCounter = null;
|
|
84
|
-
self._addEnableHandlers();
|
|
85
|
-
stanza = $build('enable', enableParams);
|
|
86
|
-
} else {
|
|
87
|
-
self._nodeBuilder = client.Stanza;
|
|
88
|
-
self._addEnableHandlers();
|
|
89
|
-
stanza = chatUtils.createStanza(self._nodeBuilder, enableParams, 'enable');
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
self._c.send(stanza);
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
StreamManagement.prototype._timeoutCallback = function () {
|
|
96
|
-
var self = this,
|
|
97
|
-
now = Date.now(),
|
|
98
|
-
updatedStanzasQueue = [];
|
|
99
|
-
|
|
100
|
-
if(self._stanzasQueue.length){
|
|
101
|
-
for(var i = 0; i < self._stanzasQueue.length; i++){
|
|
102
|
-
if(self._stanzasQueue[i] && self._stanzasQueue[i].time < now){
|
|
103
|
-
self.sentMessageCallback(self._stanzasQueue[i].message);
|
|
104
|
-
} else {
|
|
105
|
-
updatedStanzasQueue.push(self._stanzasQueue[i]);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
self._stanzasQueue = updatedStanzasQueue;
|
|
110
|
-
}
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
StreamManagement.prototype._addEnableHandlers = function () {
|
|
114
|
-
var self = this;
|
|
115
|
-
|
|
116
|
-
if (Utils.getEnv().browser) {
|
|
117
|
-
self._c.XAddTrackedHandler(_incomingStanzaHandler.bind(self));
|
|
118
|
-
} else {
|
|
119
|
-
self._c.on('stanza', _incomingStanzaHandler.bind(self));
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function _incomingStanzaHandler (stanza){
|
|
123
|
-
/*
|
|
124
|
-
* Getting incoming stanza tagName
|
|
125
|
-
* */
|
|
126
|
-
|
|
127
|
-
var tagName = stanza.name || stanza.tagName || stanza.nodeTree.tagName;
|
|
128
|
-
|
|
129
|
-
if(tagName === 'enabled'){
|
|
130
|
-
self._isStreamManagementEnabled = true;
|
|
131
|
-
|
|
132
|
-
return true;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (self._isStreamManagementEnabled && tagName === 'message') {
|
|
136
|
-
clearInterval(self._intervalId);
|
|
137
|
-
self._intervalId = setInterval(self._timeoutCallback.bind(self), self._timeInterval);
|
|
138
|
-
|
|
139
|
-
return true;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if(chatUtils.getAttr(stanza, 'xmlns') !== self._NS){
|
|
143
|
-
self._increaseReceivedStanzasCounter();
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if(tagName === 'r'){
|
|
147
|
-
var params = {
|
|
148
|
-
xmlns: self._NS,
|
|
149
|
-
h: self._clientProcessedStanzasCounter
|
|
150
|
-
},
|
|
151
|
-
answerStanza = Utils.getEnv().browser ? $build('a', params) :
|
|
152
|
-
chatUtils.createStanza(self._nodeBuilder, params, 'a');
|
|
153
|
-
|
|
154
|
-
self._originalSend.call(self._c, answerStanza);
|
|
155
|
-
|
|
156
|
-
return true;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if(tagName === 'a'){
|
|
160
|
-
var h = parseInt(chatUtils.getAttr(stanza, 'h'));
|
|
161
|
-
|
|
162
|
-
self._checkCounterOnIncomeStanza(h);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
return true;
|
|
166
|
-
}
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
StreamManagement.prototype.send = function (stanza, message) {
|
|
170
|
-
var self = this,
|
|
171
|
-
stanzaXML = stanza.nodeTree ? this._parser.parseFromString(stanza.nodeTree.outerHTML, "application/xml").childNodes[0] : stanza,
|
|
172
|
-
tagName = stanzaXML.name || stanzaXML.tagName || stanzaXML.nodeTree.tagName,
|
|
173
|
-
type = chatUtils.getAttr(stanzaXML, 'type'),
|
|
174
|
-
bodyContent = chatUtils.getElementText(stanzaXML, 'body') || '',
|
|
175
|
-
attachments = chatUtils.getAllElements(stanzaXML, 'attachment') || '';
|
|
176
|
-
|
|
177
|
-
try {
|
|
178
|
-
self._originalSend.call(self._c, stanza);
|
|
179
|
-
} catch (e) {
|
|
180
|
-
Utils.QBLog('[QBChat]', e.message);
|
|
181
|
-
} finally {
|
|
182
|
-
if (tagName === 'message' && (type === 'chat' || type === 'groupchat') && (bodyContent || attachments.length)) {
|
|
183
|
-
self._sendStanzasRequest({
|
|
184
|
-
message: message,
|
|
185
|
-
time: Date.now() + self._timeInterval,
|
|
186
|
-
expect: self._clientSentStanzasCounter
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
self._clientSentStanzasCounter++;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
StreamManagement.prototype._sendStanzasRequest = function (data) {
|
|
196
|
-
var self = this;
|
|
197
|
-
|
|
198
|
-
if(self._isStreamManagementEnabled){
|
|
199
|
-
self._stanzasQueue.push(data);
|
|
200
|
-
|
|
201
|
-
var stanza = Utils.getEnv().browser ? $build('r', { xmlns: self._NS }) :
|
|
202
|
-
chatUtils.createStanza(self._nodeBuilder, { xmlns: self._NS }, 'r');
|
|
203
|
-
|
|
204
|
-
if (self._c.connected) {
|
|
205
|
-
self._originalSend.call(self._c, stanza);
|
|
206
|
-
} else {
|
|
207
|
-
self._checkCounterOnIncomeStanza();
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
StreamManagement.prototype.getClientSentStanzasCounter = function(){
|
|
213
|
-
return this._clientSentStanzasCounter;
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
StreamManagement.prototype._checkCounterOnIncomeStanza = function (count){
|
|
217
|
-
var updatedStanzasQueue = [];
|
|
218
|
-
|
|
219
|
-
if(this._stanzasQueue.length){
|
|
220
|
-
for(var i = 0; i < this._stanzasQueue.length; i++){
|
|
221
|
-
if(this._stanzasQueue[i].expect == count){
|
|
222
|
-
this.sentMessageCallback(null, this._stanzasQueue[i].message);
|
|
223
|
-
} else {
|
|
224
|
-
updatedStanzasQueue.push(this._stanzasQueue[i]);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
this._stanzasQueue = updatedStanzasQueue;
|
|
228
|
-
}
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
StreamManagement.prototype._increaseReceivedStanzasCounter = function(){
|
|
232
|
-
this._clientProcessedStanzasCounter++;
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
module.exports = StreamManagement;
|