@cc-livekit/ttsignal 1.0.7 → 1.0.9

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/index.js CHANGED
@@ -3,10 +3,9 @@
3
3
  /*******************************************************************************
4
4
  * javascript glue wrapper of ttsignal module
5
5
  * @module index.js
6
- * @author antoniozhou.
6
+ * @author anto.
7
7
  ******************************************************************************/
8
8
 
9
- // var util = require('util');
10
9
  const EventEmitter = require("events").EventEmitter;
11
10
  const fs = require("fs");
12
11
  const path = require("path");
@@ -30,11 +29,12 @@ function resolveAddonPath() {
30
29
  }
31
30
 
32
31
  const baseDir = __dirname;
32
+ const kind = process.ttsBuildType === "debug" ? "Debug" : "Release";
33
33
  const searchRoots = [
34
- path.join(baseDir, "build", "Release"),
35
- path.join(baseDir, "dist", "build", "Release"),
36
- path.join(baseDir, "..", "build", "Release"),
37
- path.join(baseDir, "..", "dist", "build", "Release"),
34
+ path.join(baseDir, "build", kind),
35
+ path.join(baseDir, "dist", "build", kind),
36
+ path.join(baseDir, "..", "build", kind),
37
+ path.join(baseDir, "..", "dist", "build", kind),
38
38
  ];
39
39
 
40
40
  for (const root of searchRoots) {
@@ -74,18 +74,18 @@ function loadNativeAddon() {
74
74
  const ttsignal = loadNativeAddon();
75
75
 
76
76
  const CONST = {
77
- TTS_TYPE_COMMAND: 0x01,
78
- TTS_TYPE_MESSAGE: 0x02,
79
- TTS_TYPE_USER_CONTROL: 0x03,
80
- TTS_CC_BBR: 0x62,
81
- TTS_CC_BBR2: 0x42,
82
- TTS_CC_CUBIC: 0x63,
83
- TTS_CC_RENO: 0x72,
84
- LOG_LEVEL_DEBUG: 0x01,
85
- LOG_LEVEL_INFO: 0x02,
86
- LOG_LEVEL_WARN: 0x03,
87
- LOG_LEVEL_ERROR: 0x04,
88
- LOG_LEVEL_FATAL: 0x05,
77
+ TTS_TYPE_COMMAND : 0x01,
78
+ TTS_TYPE_MESSAGE : 0x02,
79
+ TTS_TYPE_USER_CONTROL : 0x03,
80
+ TTS_CC_BBR : 0x62,
81
+ TTS_CC_BBR2 : 0x42,
82
+ TTS_CC_CUBIC : 0x63,
83
+ TTS_CC_RENO : 0x72,
84
+ LOG_LEVEL_DEBUG : 0x01,
85
+ LOG_LEVEL_INFO : 0x02,
86
+ LOG_LEVEL_WARN : 0x03,
87
+ LOG_LEVEL_ERROR : 0x04,
88
+ LOG_LEVEL_FATAL : 0x05
89
89
  };
90
90
 
91
91
  //*******************************************************************************
@@ -93,47 +93,45 @@ const CONST = {
93
93
  //*******************************************************************************
94
94
 
95
95
  function copyProperties(target, source) {
96
- for (var k in source) {
97
- if (source.hasOwnProperty(k)) {
98
- target[k] = source[k];
96
+ for (var k in source){
97
+ if (source.hasOwnProperty(k)) {
98
+ target[k] = source[k];
99
+ }
99
100
  }
100
- }
101
101
  }
102
102
  copyProperties(ttsignal, CONST);
103
103
 
104
104
  function inherits(target, source) {
105
- for (var k in source.prototype) target.prototype[k] = source.prototype[k];
105
+ for (var k in source.prototype)
106
+ target.prototype[k] = source.prototype[k];
106
107
  }
107
108
  inherits(ttsignal.Connector, EventEmitter);
108
109
  inherits(ttsignal.Connection, EventEmitter);
109
110
  inherits(ttsignal.Server, EventEmitter);
110
111
  inherits(ttsignal.ServerConnection, EventEmitter);
111
112
 
113
+
112
114
  /*******************************************************************************
113
- * @class ttsignal.Connector
114
- *******************************************************************************/
115
+ * @class ttsignal.Connector
116
+ *******************************************************************************/
115
117
 
116
118
  /**
117
119
  * @method _internalCallback
118
120
  * @private
119
- *
120
- *
121
+ *
122
+ *
121
123
  **/
122
- ttsignal.Connector.prototype._internalCallback = function (
123
- type,
124
- __arg2,
125
- __arg3
126
- ) {
127
- switch (type) {
128
- case "close":
129
- this.emit("close");
130
- break;
131
- }
132
- };
124
+ ttsignal.Connector.prototype._internalCallback = function(type, __arg2, __arg3){
125
+ switch(type){
126
+ case 'close':
127
+ this.emit('close');
128
+ break;
129
+ }
130
+ }
133
131
 
134
132
  /**
135
133
  * 为特定事件添加一个监听处理程序.
136
- * 当前支持除'_error/_result/onStatus/error/close'等事件之外的
134
+ * 当前支持除'_error/_result/onStatus/error/close'等事件之外的
137
135
  * 任何自定义事件.上述事件为内部保留事件,用户不应定义与这些事件同名的
138
136
  * 远程调用函数名。与用户自定义事件相对应的事件处理函数的参数列表与远端
139
137
  * 调用时传入的参数列表一致。
@@ -184,17 +182,17 @@ ttsignal.Connector.prototype._internalCallback = function (
184
182
  * @example
185
183
  * press.createConnection(config);
186
184
  **/
187
- ttsignal.Connector.prototype.createConnection = function (config) {
188
- if (typeof config != "object") {
189
- throw Error("Invalid args value.");
190
- }
191
- var default_config = {
192
- c_cong_ctl: CONST.TTS_CC_BBR2,
193
- };
194
- copyProperties(default_config, config);
195
- let conn = this.__createConnection__(default_config);
196
- return conn;
197
- };
185
+ ttsignal.Connector.prototype.createConnection = function(config){
186
+ if (typeof(config) != 'object'){
187
+ throw Error('Invalid args value.');
188
+ }
189
+ var default_config = {
190
+ c_cong_ctl : CONST.TTS_CC_BBR2
191
+ }
192
+ copyProperties(default_config, config);
193
+ let conn = this.__createConnection__(default_config);
194
+ return conn;
195
+ }
198
196
 
199
197
  /**
200
198
  * 关闭。
@@ -205,73 +203,84 @@ ttsignal.Connector.prototype.createConnection = function (config) {
205
203
  * @example
206
204
  * connector.close();
207
205
  **/
208
- ttsignal.Connector.prototype.close = function () {
209
- this.__close__();
210
- };
206
+ ttsignal.Connector.prototype.close = function(){
207
+ this.__close__();
208
+ }
209
+
211
210
 
212
211
  /*******************************************************************************
213
- * @class ttsignal.Connection
214
- *******************************************************************************/
212
+ * @class ttsignal.Connection
213
+ *******************************************************************************/
215
214
 
216
215
  /**
217
216
  * @method _internalCallback
218
217
  * @private
219
- *
220
- *
218
+ *
219
+ *
221
220
  **/
222
- ttsignal.Connection.prototype._internalCallback = function (
223
- type,
224
- __arg2,
225
- __arg3
226
- ) {
227
- let self = this;
228
- switch (type) {
229
- case "handshakeFinished":
230
- this.streams = {};
231
- this.emit("handshakeFinished");
232
- break;
233
- case "streamCreated":
234
- if (this.streams.hasOwnProperty(__arg2)) {
235
- break;
236
- }
237
- var stream = new ttsignal.Stream(this, __arg2);
238
- this.streams[__arg2] = stream;
239
- this.emit("streamCreated", stream);
240
- break;
241
- case "streamClosed":
242
- if (!this.streams.hasOwnProperty(__arg2)) {
243
- break;
244
- }
245
- var stream = this.streams[__arg2];
246
- delete this.streams[__arg2];
247
- stream.onClose();
248
- break;
249
- case "command":
250
- if (!this.streams.hasOwnProperty(__arg2)) {
251
- break;
252
- }
253
- var stream = this.streams[__arg2];
254
- stream.onCommand(__arg3);
255
- break;
256
- case "data":
257
- if (!this.streams.hasOwnProperty(__arg2)) {
258
- break;
259
- }
260
- var stream = this.streams[__arg2];
261
- stream.onData(__arg3);
262
- break;
263
- case "restart":
264
- this.emit("restart", __arg2, __arg3);
265
- break;
266
- case "close":
267
- this.emit("close", __arg2);
268
- break;
269
- }
270
- };
221
+ ttsignal.Connection.prototype._internalCallback = function(type, __arg2, __arg3, __arg4, __arg5){
222
+ let self = this;
223
+ switch(type){
224
+ case 'handshakeFinished':
225
+ this.streams = {};
226
+ this.emit('handshakeFinished');
227
+ break;
228
+ case 'streamCreated':
229
+ if (this.streams.hasOwnProperty(__arg2)) {
230
+ break;
231
+ }
232
+ var stream = new ttsignal.Stream(this, __arg2);
233
+ this.streams[__arg2] = stream;
234
+ this.emit('streamCreated', stream);
235
+ break;
236
+ case 'streamClosed':
237
+ if (!this.streams.hasOwnProperty(__arg2)) {
238
+ break;
239
+ }
240
+ var stream = this.streams[__arg2];
241
+ delete this.streams[__arg2];
242
+ stream.onClose();
243
+ break;
244
+ case 'streamDataAcked':
245
+ if (!this.streams.hasOwnProperty(__arg2)) {
246
+ break;
247
+ }
248
+ var stream = this.streams[__arg2];
249
+ stream.onDataAcked(__arg3, __arg4, __arg5);
250
+ break;
251
+ case 'streamDataSent':
252
+ if (!this.streams.hasOwnProperty(__arg2)) {
253
+ break;
254
+ }
255
+ var stream = this.streams[__arg2];
256
+ stream.onDataSent(__arg3, __arg4);
257
+ break;
258
+ case 'command':
259
+ if (!this.streams.hasOwnProperty(__arg2)) {
260
+ break;
261
+ }
262
+ var stream = this.streams[__arg2];
263
+ stream.onCommand(__arg3);
264
+ break;
265
+ case 'data':
266
+ if (!this.streams.hasOwnProperty(__arg2)) {
267
+ break;
268
+ }
269
+ var stream = this.streams[__arg2];
270
+ stream.onData(__arg3, __arg4);
271
+ break;
272
+ case 'restart':
273
+ this.emit('restart', __arg2, __arg3);
274
+ break;
275
+ case 'close':
276
+ this.emit('close', __arg2);
277
+ break;
278
+ }
279
+ }
271
280
 
272
281
  /**
273
282
  * 为特定事件添加一个监听处理程序.
274
- * 当前支持除'_error/_result/onStatus/error/close'等事件之外的
283
+ * 当前支持除'_error/_result/onStatus/error/close'等事件之外的
275
284
  * 任何自定义事件.上述事件为内部保留事件,用户不应定义与这些事件同名的
276
285
  * 远程调用函数名。与用户自定义事件相对应的事件处理函数的参数列表与远端
277
286
  * 调用时传入的参数列表一致。
@@ -336,31 +345,26 @@ ttsignal.Connection.prototype._internalCallback = function (
336
345
  * console.log(result);
337
346
  * });
338
347
  **/
339
- ttsignal.Connection.prototype.connect = function (
340
- url,
341
- args,
342
- timeoutInMs,
343
- callback
344
- ) {
345
- if (typeof url != "string") {
346
- throw Error("Invalid url value.");
347
- }
348
- if (typeof callback != "function") {
349
- throw Error("Invalid callback value.");
350
- }
351
- this.__connect__(url, JSON.stringify(args), timeoutInMs, (err, response) => {
352
- if (typeof response == "string") {
353
- try {
354
- props = JSON.parse(response);
355
- callback(err, props);
356
- } catch (e) {
357
- callback(err, response);
358
- }
359
- } else {
360
- callback(err, null);
361
- }
362
- });
363
- };
348
+ ttsignal.Connection.prototype.connect = function(url, args, timeoutInMs, callback){
349
+ if (typeof(url) != 'string'){
350
+ throw Error('Invalid url value.');
351
+ }
352
+ if (typeof(callback) != 'function'){
353
+ throw Error('Invalid callback value.');
354
+ }
355
+ this.__connect__(url, JSON.stringify(args), timeoutInMs, (err, response)=>{
356
+ if (typeof response == 'string') {
357
+ try {
358
+ props = JSON.parse(response);
359
+ callback(err, props);
360
+ } catch (e) {
361
+ callback(err, response);
362
+ }
363
+ } else {
364
+ callback(err, null);
365
+ }
366
+ });
367
+ }
364
368
 
365
369
  /**
366
370
  * 重新创建底层socket。
@@ -371,9 +375,9 @@ ttsignal.Connection.prototype.connect = function (
371
375
  * @example
372
376
  * conn.restart();
373
377
  **/
374
- ttsignal.Connection.prototype.restart = function () {
375
- this.__restart__();
376
- };
378
+ ttsignal.Connection.prototype.restart = function(){
379
+ this.__restart__();
380
+ }
377
381
 
378
382
  /**
379
383
  * 关闭。
@@ -384,175 +388,345 @@ ttsignal.Connection.prototype.restart = function () {
384
388
  * @example
385
389
  * conn.close();
386
390
  **/
387
- ttsignal.Connection.prototype.close = function () {
388
- this.__close__();
389
- };
391
+ ttsignal.Connection.prototype.close = function(){
392
+ this.__close__();
393
+ }
390
394
 
391
395
  /*******************************************************************************
392
- * @class ttsignal.Stream
393
- *******************************************************************************/
394
-
395
- class Stream extends EventEmitter {
396
- constructor(conn, streamId) {
397
- super();
398
- this.conn = conn;
399
- this.streamId = streamId;
400
- this.nextTransId = 2;
401
- this.stubs = {};
402
- }
396
+ * @class ttsignal.Stream
397
+ *******************************************************************************/
403
398
 
404
- onCommand(cmdStr) {
405
- let self = this;
406
- try {
407
- cmd = JSON.parse(cmdStr);
408
- if (typeof cmd != "object") {
409
- throw Error("Invalid command value." + __arg2);
410
- }
411
- if (!cmd.hasOwnProperty("name")) {
412
- throw Error(
413
- 'Invalid command value, MUST have "name" property.' + __arg2
414
- );
415
- }
416
- if (cmd.name == "_error" || cmd.name == "_result") {
417
- if (self.stubs.hasOwnProperty(cmd.transId)) {
418
- self.stubs[cmd.transId](cmd);
419
- delete self.stubs[cmd.transId];
399
+ class Stream extends EventEmitter {
400
+ constructor(conn, streamId){
401
+ super();
402
+ this.conn = conn;
403
+ this.streamId = streamId;
404
+ this.nextTransId = 2;
405
+ this.stubs = {};
406
+ this.dataStreams = {};
407
+ }
408
+ onCommand(cmdStr){
409
+ let self = this;
410
+ try {
411
+ let cmd = JSON.parse(cmdStr)
412
+ if (typeof(cmd) != 'object') {
413
+ throw Error('Invalid command value.' + __arg2);
414
+ }
415
+ if (!cmd.hasOwnProperty('name')){
416
+ throw Error('Invalid command value, MUST have "name" property.' + __arg2);
417
+ }
418
+ if (cmd.name == '_error' || cmd.name == '_result' || cmd.name == 'onStatus'){
419
+ if (self.stubs.hasOwnProperty(cmd.transId)) {
420
+ self.stubs[cmd.transId](cmd);
421
+ let keepStub = cmd.name == 'onStatus'
422
+ if (!keepStub) {
423
+ delete self.stubs[cmd.transId];
424
+ }
425
+ }
426
+ } else {
427
+ if (cmd.hasOwnProperty('transId')) {
428
+ cmd.echoResult = function(result){
429
+ self.sendCommand({
430
+ name: '_result',
431
+ transId: cmd.transId,
432
+ result: result
433
+ });
434
+ }
435
+ cmd.echoError = function(error){
436
+ self.sendCommand({
437
+ name: '_error',
438
+ transId: cmd.transId,
439
+ error: error
440
+ });
441
+ }
442
+ } else {
443
+ cmd.echoResult = ()=>{};
444
+ cmd.echoError = ()=>{};
445
+ }
446
+ self.emit(cmd.name, cmd);
447
+ }
448
+ } catch (error) {
449
+ console.error('parse command failed', error);
450
+ return;
420
451
  }
421
- } else {
422
- if (cmd.hasOwnProperty("transId")) {
423
- cmd.echoResult = function (result) {
424
- self.sendCommand({
425
- name: "_result",
426
- transId: cmd.transId,
427
- result: result,
428
- });
429
- };
430
- cmd.echoError = function (error) {
431
- self.sendCommand({
432
- name: "_error",
433
- transId: cmd.transId,
434
- error: error,
435
- });
436
- };
437
- } else {
438
- cmd.echoResult = () => {};
439
- cmd.echoError = () => {};
452
+ }
453
+ onData(data, transId){
454
+ if (transId && this.dataStreams.hasOwnProperty(transId)) {
455
+ let ds = this.dataStreams[transId];
456
+ if (data.length === 0) {
457
+ delete this.dataStreams[transId];
458
+ ds.emit('end');
459
+ } else {
460
+ ds.emit('data', data);
461
+ }
462
+ return;
440
463
  }
441
- self.emit(cmd.name, cmd);
442
- }
443
- } catch (error) {
444
- console.error("parse command failed", error);
445
- return;
464
+ this.emit('data', data);
446
465
  }
447
- }
448
466
 
449
- onData(data) {
450
- this.emit("data", data);
451
- }
467
+ onClose(){
468
+ for (let tid in this.dataStreams) {
469
+ this.dataStreams[tid].emit('end');
470
+ }
471
+ this.dataStreams = {};
472
+ this.emit('close');
473
+ }
452
474
 
453
- onClose() {
454
- this.emit("close");
455
- }
475
+ /** QUIC 发送侧:数据确认回调;emit `dataAcked`(ackDelayTimeµs, ackedBytes, inflightBytes)。 */
476
+ onDataAcked(ackDelayTime, ackedBytes, inflightBytes){
477
+ this.emit('dataAcked', ackDelayTime, ackedBytes, inflightBytes);
478
+ }
456
479
 
457
- /**
458
- * 发送命令.
459
- *
460
- * @method sendCommand
461
- * @public
462
- * @param timestamp {Number} timestamp.
463
- * @param cmd {Buffer} commnd to send.
464
- * @example
465
- * conn.sendCommand(cmd);
466
- **/
467
- sendCommand(cmd, callback) {
468
- if (typeof cmd != "object") {
469
- throw Error("Invalid command value.");
470
- }
471
- if (!cmd.hasOwnProperty("name")) {
472
- throw Error('Invalid command value, MUST have "name" property.');
473
- }
474
- if (typeof callback === "function") {
475
- cmd.transId = this.nextTransId++;
476
- this.stubs[cmd.transId] = callback;
480
+ /** QUIC 发送侧:数据已从待发队列写入传输;emit `dataSent`(nTransId, size)。putFile 返回的 ws 仅转发本 transId 为 `dataSent`(size)。 */
481
+ onDataSent(nTransId, size){
482
+ this.emit('dataSent', nTransId, size);
477
483
  }
478
- let msg = JSON.stringify(cmd);
479
- let buf = Buffer.from(msg, "utf8");
480
- this.conn.__sendPacket__(
481
- CONST.TTS_TYPE_COMMAND,
482
- new Date().getTime(),
483
- 0,
484
- this.streamId,
485
- buf
486
- );
487
- }
488
484
 
489
- /**
490
- * 发送数据.
491
- *
492
- * @method sendData
493
- * @public
494
- * @param timestamp {Number} timestamp.
495
- * @param data {Buffer} data to send.
496
- * @example
497
- * conn.sendData(data);
498
- **/
499
- sendData(data) {
500
- if (data instanceof Buffer == false) {
501
- throw Error("Invalid data type, MUST be Buffer.");
502
- }
503
- this.conn.__sendPacket__(
504
- CONST.TTS_TYPE_MESSAGE,
505
- new Date().getTime(),
506
- 0,
507
- this.streamId,
508
- data
509
- );
510
- }
485
+ /**
486
+ * 发送命令.
487
+ *
488
+ * @method sendCommand
489
+ * @public
490
+ * @param cmd {Object} command to send.
491
+ * @param callback {Function} callback function.
492
+ * @example
493
+ * conn.sendCommand(cmd);
494
+ **/
495
+ sendCommand(cmd, callback){
496
+ if (typeof(cmd) != 'object') {
497
+ throw Error('Invalid command value.');
498
+ }
499
+ if (!cmd.hasOwnProperty('name')){
500
+ throw Error('Invalid command value, MUST have "name" property.');
501
+ }
502
+ if (typeof callback === 'function') {
503
+ cmd.transId = this.nextTransId++;
504
+ this.stubs[cmd.transId] = callback;
505
+ }
506
+ let msg = JSON.stringify(cmd);
507
+ let buf = Buffer.from(msg, 'utf8');
508
+ this.conn.__sendPacket__(CONST.TTS_TYPE_COMMAND, (new Date).getTime(),
509
+ cmd.transId, this.streamId, buf);
510
+ }
511
511
 
512
- /**
513
- * 关闭。
514
- *
515
- * @method close
516
- * @public
517
- * @sync
518
- * @example
519
- * conn.close();
520
- **/
521
- close() {
522
- this.conn.__closeStream__(this.streamId);
523
- }
512
+ /**
513
+ * 发送数据.
514
+ *
515
+ * @method sendData
516
+ * @public
517
+ * @param timestamp {Number} timestamp.
518
+ * @param data {Buffer} data to send.
519
+ * @example
520
+ * conn.sendData(data);
521
+ **/
522
+ sendData(data){
523
+ if (data instanceof Buffer == false) {
524
+ throw Error('Invalid data type, MUST be Buffer.');
525
+ }
526
+ this.conn.__sendPacket__(CONST.TTS_TYPE_MESSAGE, (new Date).getTime(),
527
+ 0, this.streamId, data);
528
+ }
529
+
530
+ /**
531
+ * 请求文件(数据流下载)。
532
+ *
533
+ * @method getFile
534
+ * @public
535
+ * @param req {Object} 请求参数,如 {path:"index.html"}
536
+ * @param callback {Function} 命令响应回调,透传给底层 __sendPacket__
537
+ * @return {EventEmitter} 数据流对象,支持 'data' 和 'end' 事件
538
+ * @example
539
+ * let ds = stream.getFile({path:"index.html"}, (cmd)=>{
540
+ * console.log('response:', cmd);
541
+ * });
542
+ * ds.on('data', (chunk) => { ... });
543
+ * ds.on('end', () => { ... });
544
+ **/
545
+ getFile(args, callback){
546
+ if (typeof(args) != 'object') {
547
+ throw Error('Invalid request value.');
548
+ }
549
+ if (!args.hasOwnProperty('path')) {
550
+ throw Error('Invalid request value, MUST have "path" property.');
551
+ }
552
+ args.method = 'GET';
553
+ let req = {
554
+ name: 'staticFile',
555
+ props: args
556
+ };
557
+ let self = this;
558
+ let transId = this.nextTransId++;
559
+ req.transId = transId;
560
+ if (typeof callback === 'function') {
561
+ this.stubs[transId] = callback;
562
+ }
563
+ let ds = new EventEmitter();
564
+ ds.once('end', () => { delete self.dataStreams[transId]; });
565
+ this.dataStreams[transId] = ds;
566
+ let msg = JSON.stringify(req);
567
+ let buf = Buffer.from(msg, 'utf8');
568
+ this.conn.__sendPacket__(CONST.TTS_TYPE_COMMAND, (new Date).getTime(),
569
+ transId, this.streamId, buf);
570
+ return ds;
571
+ }
572
+
573
+ /**
574
+ * 上传文件(数据流上传)。
575
+ *
576
+ * @method putFile
577
+ * @public
578
+ * @param req {Object} 请求参数,如 {path:"upload.bin"}
579
+ * @param callback {Function} 命令响应回调
580
+ * @return {events.EventEmitter} 写入流:write(data)、end(),并可 on('dataSent', (size)=>{})(仅本 putFile 事务)。
581
+ * @example
582
+ * let ws = stream.putFile({path:"upload.bin"}, (cmd)=>{
583
+ * console.log('response:', cmd);
584
+ * });
585
+ * ws.on('dataSent', (size) => {});
586
+ * ws.write(chunk1);
587
+ * ws.write(chunk2);
588
+ * ws.end();
589
+ **/
590
+ putFile(args, callback){
591
+ if (typeof(args) != 'object') {
592
+ throw Error('Invalid request value.');
593
+ }
594
+ if (!args.hasOwnProperty('path')) {
595
+ throw Error('Invalid request value, MUST have "path" property.');
596
+ }
597
+ if (!args.hasOwnProperty('size')) {
598
+ throw Error('Invalid request value, MUST have "path" property.');
599
+ }
600
+ args.method = 'PUT';
601
+ let req = {
602
+ name: 'staticFile',
603
+ props: args
604
+ };
605
+ let self = this;
606
+ let transId = this.nextTransId++;
607
+ req.transId = transId;
608
+ if (typeof callback === 'function') {
609
+ this.stubs[transId] = callback;
610
+ }
611
+ let msg = JSON.stringify(req);
612
+ let buf = Buffer.from(msg, 'utf8');
613
+ this.conn.__sendPacket__(CONST.TTS_TYPE_COMMAND, (new Date).getTime(),
614
+ transId, this.streamId, buf);
615
+ let ended = false;
616
+ let ws = new EventEmitter();
617
+ let onDataSent = (nTransId, size) => {
618
+ if (nTransId == transId) {
619
+ ws.emit('dataSent', size);
620
+ }
621
+ }
622
+ this.on('dataSent', onDataSent);
623
+ ws.write = (data) => {
624
+ if (ended) {
625
+ throw Error('Write after end.');
626
+ }
627
+ if (data instanceof Buffer == false) {
628
+ throw Error('Invalid data type, MUST be Buffer.');
629
+ }
630
+ self.conn.__sendPacket__(CONST.TTS_TYPE_MESSAGE, (new Date).getTime(),
631
+ transId, self.streamId, data);
632
+ }
633
+ ws.end = () => {
634
+ if (ended) return;
635
+ ended = true;
636
+ self.conn.__sendPacket__(CONST.TTS_TYPE_MESSAGE, (new Date).getTime(),
637
+ transId, self.streamId, Buffer.alloc(0));
638
+ self.removeListener('dataSent', onDataSent);
639
+ }
640
+ return ws;
641
+ }
642
+
643
+ /**
644
+ * 请求文件(数据流下载)。
645
+ *
646
+ * @method getLogFile
647
+ * @public
648
+ * @param req {Object} 请求参数,如 {path:"room_name"}
649
+ * @param callback {Function} 命令响应回调,透传给底层 __sendPacket__
650
+ * @return {EventEmitter} 数据流对象,支持 'data' 和 'end' 事件
651
+ * @example
652
+ * let ds = stream.getLogFile({path:"room_name"}, (cmd)=>{
653
+ * console.log('response:', cmd);
654
+ * });
655
+ * ds.on('data', (chunk) => { ... });
656
+ * ds.on('end', () => { ... });
657
+ **/
658
+ getLogFile(args, callback){
659
+ if (typeof(args) != 'object') {
660
+ throw Error('Invalid request value.');
661
+ }
662
+ if (!args.hasOwnProperty('roomId')) {
663
+ throw Error('Invalid request value, MUST have "roomId" property.');
664
+ }
665
+ args.method = 'GET';
666
+ let req = {
667
+ name: 'logFile',
668
+ props: args
669
+ };
670
+ let self = this;
671
+ let transId = this.nextTransId++;
672
+ req.transId = transId;
673
+ if (typeof callback === 'function') {
674
+ this.stubs[transId] = callback;
675
+ }
676
+ let ds = new EventEmitter();
677
+ ds.once('end', () => { delete self.dataStreams[transId]; });
678
+ this.dataStreams[transId] = ds;
679
+ let msg = JSON.stringify(req);
680
+ let buf = Buffer.from(msg, 'utf8');
681
+ this.conn.__sendPacket__(CONST.TTS_TYPE_COMMAND, (new Date).getTime(),
682
+ transId, this.streamId, buf);
683
+ return ds;
684
+ }
685
+
686
+ /**
687
+ * 关闭。
688
+ *
689
+ * @method close
690
+ * @public
691
+ * @sync
692
+ * @example
693
+ * conn.close();
694
+ **/
695
+ close(){
696
+ this.conn.__closeStream__(this.streamId);
697
+ }
524
698
  }
525
699
  ttsignal.Stream = Stream;
526
700
 
527
701
  /*******************************************************************************
528
- * @class ttsignal.Server
529
- *******************************************************************************/
702
+ * @class ttsignal.Server
703
+ *******************************************************************************/
530
704
 
531
705
  /**
532
706
  * @method _internalCallback
533
707
  * @private
534
- *
535
- *
708
+ *
709
+ *
536
710
  **/
537
- ttsignal.Server.prototype._internalCallback = function (type, __arg2, __arg3) {
538
- switch (type) {
539
- case "connection":
540
- if (__arg2 instanceof ttsignal.ServerConnection) {
541
- let conn = __arg2;
542
- conn.nextTransId = 2;
543
- conn.stubs = {};
544
- this.emit("connection", conn);
545
- }
546
- break;
547
- case "close":
548
- this.emit("close");
549
- break;
550
- }
551
- };
711
+ ttsignal.Server.prototype._internalCallback = function(type, __arg2, __arg3){
712
+ switch(type){
713
+ case 'connection':
714
+ if (__arg2 instanceof ttsignal.ServerConnection) {
715
+ let conn = __arg2;
716
+ conn.nextTransId = 2;
717
+ conn.stubs = {};
718
+ this.emit('connection', conn);
719
+ }
720
+ break;
721
+ case 'close':
722
+ this.emit('close');
723
+ break;
724
+ }
725
+ }
552
726
 
553
727
  /**
554
728
  * 为特定事件添加一个监听处理程序.
555
- * 当前支持除'_error/_result/onStatus/error/close'等事件之外的
729
+ * 当前支持除'_error/_result/onStatus/error/close'等事件之外的
556
730
  * 任何自定义事件.上述事件为内部保留事件,用户不应定义与这些事件同名的
557
731
  * 远程调用函数名。与用户自定义事件相对应的事件处理函数的参数列表与远端
558
732
  * 调用时传入的参数列表一致。
@@ -603,9 +777,9 @@ ttsignal.Server.prototype._internalCallback = function (type, __arg2, __arg3) {
603
777
  * @example
604
778
  * connector.start();
605
779
  **/
606
- ttsignal.Server.prototype.start = function () {
607
- this.__start__();
608
- };
780
+ ttsignal.Server.prototype.start = function(){
781
+ this.__start__();
782
+ }
609
783
 
610
784
  /**
611
785
  * 关闭服务器。
@@ -616,93 +790,88 @@ ttsignal.Server.prototype.start = function () {
616
790
  * @example
617
791
  * connector.close();
618
792
  **/
619
- ttsignal.Server.prototype.close = function () {
620
- this.__close__();
621
- };
793
+ ttsignal.Server.prototype.close = function(){
794
+ this.__close__();
795
+ }
796
+
622
797
 
623
798
  /*******************************************************************************
624
- * @class ttsignal.ServerConnection
625
- *******************************************************************************/
799
+ * @class ttsignal.ServerConnection
800
+ *******************************************************************************/
626
801
 
627
802
  /**
628
803
  * @method _internalCallback
629
804
  * @private
630
- *
631
- *
805
+ *
806
+ *
632
807
  **/
633
- ttsignal.ServerConnection.prototype._internalCallback = function (
634
- type,
635
- __arg2,
636
- __arg3
637
- ) {
638
- var self = this;
639
- switch (type) {
640
- case "handshakeFinished":
641
- this.emit("handshakeFinished");
642
- break;
643
- case "connect":
644
- try {
645
- props = JSON.parse(__arg2);
646
- this.emit("connect", props);
647
- } catch (e) {
648
- this.emit("connect", e);
649
- }
650
- break;
651
- case "command":
652
- try {
653
- cmd = JSON.parse(__arg2);
654
- if (typeof cmd != "object") {
655
- throw Error("Invalid command value." + __arg2);
656
- }
657
- if (!cmd.hasOwnProperty("name")) {
658
- throw Error(
659
- 'Invalid command value, MUST have "name" property.' + __arg2
660
- );
661
- }
662
- if (cmd.name == "_error" || cmd.name == "_result") {
663
- if (self.stubs.hasOwnProperty(cmd.transId)) {
664
- self.stubs[cmd.transId](cmd);
665
- delete self.stubs[cmd.transId];
666
- }
667
- } else {
668
- if (cmd.hasOwnProperty("transId")) {
669
- cmd.echoResult = function (result) {
670
- self.sendCommand({
671
- name: "_result",
672
- transId: cmd.transId,
673
- result: result,
674
- });
675
- };
676
- cmd.echoError = function (error) {
677
- self.sendCommand({
678
- name: "_error",
679
- transId: cmd.transId,
680
- error: error,
681
- });
682
- };
683
- } else {
684
- cmd.echoResult = () => {};
685
- cmd.echoError = () => {};
686
- }
687
- self.emit(cmd.name, cmd);
688
- }
689
- } catch (error) {
690
- console.error("parse command failed", error);
691
- return;
692
- }
693
- break;
694
- case "data":
695
- this.emit("data", __arg2);
696
- break;
697
- case "close":
698
- this.emit("close", __arg2);
699
- break;
700
- }
701
- };
808
+ ttsignal.ServerConnection.prototype._internalCallback = function(type, __arg2, __arg3){
809
+ var self = this;
810
+ switch(type){
811
+ case 'handshakeFinished':
812
+ this.emit('handshakeFinished');
813
+ break;
814
+ case 'connect':
815
+ try {
816
+ props = JSON.parse(__arg2);
817
+ this.emit('connect', props);
818
+ } catch (e) {
819
+ this.emit('connect', e);
820
+ }
821
+ break;
822
+ case 'command':
823
+ try {
824
+ cmd = JSON.parse(__arg2);
825
+ if (typeof(cmd) != 'object') {
826
+ throw Error('Invalid command value.' + __arg2);
827
+ }
828
+ if (!cmd.hasOwnProperty('name')){
829
+ throw Error('Invalid command value, MUST have "name" property.' + __arg2);
830
+ }
831
+ if (cmd.name == '_error' || cmd.name == '_result'){
832
+ if (self.stubs.hasOwnProperty(cmd.transId)) {
833
+ self.stubs[cmd.transId](cmd);
834
+ delete self.stubs[cmd.transId];
835
+ }
836
+ } else {
837
+ if (cmd.hasOwnProperty('transId')) {
838
+ cmd.echoResult = function(result){
839
+ self.sendCommand({
840
+ name: '_result',
841
+ transId: cmd.transId,
842
+ result: result
843
+ });
844
+ }
845
+ cmd.echoError = function(error){
846
+ self.sendCommand({
847
+ name: '_error',
848
+ transId: cmd.transId,
849
+ error: error
850
+ });
851
+ }
852
+ } else {
853
+ cmd.echoResult = ()=>{};
854
+ cmd.echoError = ()=>{};
855
+ }
856
+ self.emit(cmd.name, cmd);
857
+ }
858
+ } catch (error) {
859
+ console.error('parse command failed', error);
860
+ return;
861
+ }
862
+ break;
863
+ case 'data':
864
+ this.emit('data', __arg2);
865
+ break;
866
+ case 'close':
867
+ this.emit('close', __arg2);
868
+ break;
869
+ }
870
+ }
702
871
 
703
872
  /**
704
873
  * 为特定事件添加一个监听处理程序.
705
- * 当前支持除'_error/_result/onStatus/error/close'等事件之外的
874
+ * 当前支持除'_error/_result/onStatus/error/close'等事件之外的
706
875
  * 任何自定义事件.上述事件为内部保留事件,用户不应定义与这些事件同名的
707
876
  * 远程调用函数名。与用户自定义事件相对应的事件处理函数的参数列表与远端
708
877
  * 调用时传入的参数列表一致。
@@ -749,26 +918,28 @@ ttsignal.ServerConnection.prototype._internalCallback = function (
749
918
  *
750
919
  * @method sendCommand
751
920
  * @public
752
- * @param timestamp {Number} timestamp.
753
- * @param cmd {Buffer} commnd to send.
921
+ * @param cmd {Object} command to send.
922
+ * @param callback {Function} callback function.
754
923
  * @example
755
- * conn.sendCommand(cmd);
924
+ * conn.sendCommand(cmd, function(result){
925
+ * console.log(result);
926
+ * });
756
927
  **/
757
- ttsignal.ServerConnection.prototype.sendCommand = function (cmd) {
758
- if (typeof cmd != "object") {
759
- throw Error("Invalid command value.");
760
- }
761
- if (!cmd.hasOwnProperty("name")) {
762
- throw Error('Invalid command value, MUST have "name" property.');
763
- }
764
- if (typeof callback === "function") {
765
- cmd.transId = this.nextTransId++;
766
- this.stubs[cmd.transId] = callback;
767
- }
768
- let msg = JSON.stringify(cmd);
769
- let buf = Buffer.from(msg, "utf8");
770
- this.__sendPacket__(CONST.TTS_TYPE_COMMAND, new Date().getTime(), 0, buf);
771
- };
928
+ ttsignal.ServerConnection.prototype.sendCommand = function(cmd, callback){
929
+ if (typeof(cmd) != 'object') {
930
+ throw Error('Invalid command value.');
931
+ }
932
+ if (!cmd.hasOwnProperty('name')){
933
+ throw Error('Invalid command value, MUST have "name" property.');
934
+ }
935
+ if (typeof callback === 'function') {
936
+ cmd.transId = this.nextTransId++;
937
+ this.stubs[cmd.transId] = callback;
938
+ }
939
+ let msg = JSON.stringify(cmd);
940
+ let buf = Buffer.from(msg, 'utf8');
941
+ this.__sendPacket__(CONST.TTS_TYPE_COMMAND, (new Date).getTime(), cmd.transId, 0, buf);
942
+ }
772
943
 
773
944
  /**
774
945
  * 发送数据.
@@ -780,12 +951,12 @@ ttsignal.ServerConnection.prototype.sendCommand = function (cmd) {
780
951
  * @example
781
952
  * conn.sendData(data);
782
953
  **/
783
- ttsignal.ServerConnection.prototype.sendData = function (data) {
784
- if (data instanceof Buffer == false) {
785
- throw Error("Invalid data type, MUST be Buffer.");
786
- }
787
- this.__sendPacket__(CONST.TTS_TYPE_MESSAGE, new Date().getTime(), 0, data);
788
- };
954
+ ttsignal.ServerConnection.prototype.sendData = function(data){
955
+ if (data instanceof Buffer == false) {
956
+ throw Error('Invalid data type, MUST be Buffer.');
957
+ }
958
+ this.__sendPacket__(CONST.TTS_TYPE_MESSAGE, (new Date).getTime(), 0, data);
959
+ }
789
960
 
790
961
  /**
791
962
  * 接受连接。
@@ -796,12 +967,12 @@ ttsignal.ServerConnection.prototype.sendData = function (data) {
796
967
  * @example
797
968
  * conn.accept(true, { server_param: 'server param' });
798
969
  **/
799
- ttsignal.ServerConnection.prototype.accept = function (accept, result) {
800
- if (typeof accept != "boolean") {
801
- throw Error("Invalid accept value.");
802
- }
803
- this.__accept__(accept, JSON.stringify(result));
804
- };
970
+ ttsignal.ServerConnection.prototype.accept = function(accept, result){
971
+ if (typeof(accept) != 'boolean') {
972
+ throw Error('Invalid accept value.');
973
+ }
974
+ this.__accept__(accept, JSON.stringify(result));
975
+ }
805
976
 
806
977
  /**
807
978
  * 关闭。
@@ -812,13 +983,13 @@ ttsignal.ServerConnection.prototype.accept = function (accept, result) {
812
983
  * @example
813
984
  * conn.close();
814
985
  **/
815
- ttsignal.ServerConnection.prototype.close = function () {
816
- this.__close__();
817
- };
986
+ ttsignal.ServerConnection.prototype.close = function(){
987
+ this.__close__();
988
+ }
818
989
 
819
990
  /*******************************************************************************
820
- * @class
821
- *******************************************************************************/
991
+ * @class
992
+ *******************************************************************************/
822
993
 
823
994
  /**
824
995
  * 创建连接器.
@@ -826,18 +997,36 @@ ttsignal.ServerConnection.prototype.close = function () {
826
997
  * @method createConnector
827
998
  * @public
828
999
  * @param config {Object} configure info.
1000
+ * @param config.alpn {String} required, ALPN string ('ttsignal' on the wire regardless).
1001
+ * @param config.ca_cert_pem {String=} optional, custom root CA in PEM format.
1002
+ * @param config.disableAutoRestart {Boolean=} optional, default `false`.
1003
+ * When `false` (default) ttsignal starts a platform-native path-change
1004
+ * monitor (NWPathMonitor on macOS, NETLINK_ROUTE on Linux,
1005
+ * NotifyIpInterfaceChange on Windows) and automatically restarts the
1006
+ * underlying UDP socket whenever the OS reports a different default
1007
+ * interface (Wi-Fi <-> ethernet, Wi-Fi <-> wired, VPN up/down). Each
1008
+ * auto-restart fires the existing `connection.on('restart', cb)` event,
1009
+ * so application code does NOT need to call `connection.restart()`
1010
+ * manually. Set `disableAutoRestart: true` for long-lived server
1011
+ * deployments where the box never roams.
829
1012
  * @example
830
- * var succeed = ttsignal.createConnector(config);
1013
+ * var connector = ttsignal.createConnector({
1014
+ * alpn: 'ttsignal',
1015
+ * disableAutoRestart: false, // default
1016
+ * });
831
1017
  **/
832
- ttsignal.createConnector = function (config) {
833
- if (typeof config !== "object") {
834
- throw Error("Invalid config.");
835
- }
836
- if (!config.alpn) {
837
- throw Error("Invalid alpn value.");
838
- }
839
- return ttsignal.__createConnector__(config);
840
- };
1018
+ ttsignal.createConnector = function(config){
1019
+ if (typeof config !== 'object') {
1020
+ throw Error('Invalid config.');
1021
+ }
1022
+ if (!config.alpn){
1023
+ throw Error('Invalid alpn value.');
1024
+ }
1025
+ if (config.caCertPem && !config.ca_cert_pem) {
1026
+ config.ca_cert_pem = config.caCertPem;
1027
+ }
1028
+ return ttsignal.__createConnector__(config);
1029
+ }
841
1030
 
842
1031
  /**
843
1032
  * 创建服务器.
@@ -848,23 +1037,21 @@ ttsignal.createConnector = function (config) {
848
1037
  * @example
849
1038
  * var succeed = ttsignal.createServer(config);
850
1039
  **/
851
- ttsignal.createServer = function (config) {
852
- if (typeof config !== "object") {
853
- throw Error("Invalid config.");
854
- }
855
- if (!config.alpn) {
856
- throw Error("Invalid alpn value.");
857
- }
858
- return ttsignal.__createServer__(config);
859
- };
1040
+ ttsignal.createServer = function(config){
1041
+ if (typeof config !== 'object') {
1042
+ throw Error('Invalid config.');
1043
+ }
1044
+ if (!config.alpn){
1045
+ throw Error('Invalid alpn value.');
1046
+ }
1047
+ return ttsignal.__createServer__(config);
1048
+ }
860
1049
 
861
1050
  //*******************************************************************************
862
- // Exports :
1051
+ // Exports :
863
1052
  //*******************************************************************************
864
1053
 
865
- // Export for both CommonJS (require) and ESM (dynamic import default)
866
- // module.exports = ttsignal;
867
- exports.ttsignal = ttsignal;
1054
+ module.exports = ttsignal;
868
1055
 
869
1056
  //*******************************************************************************
870
1057
  // End of file : ttsignal.js
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cc-livekit/ttsignal",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"