@babblevoice/babble-drachtio-callmanager 2.3.8 → 2.3.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/jsconfig.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "compilerOptions": {
3
+ "module": "commonJS",
4
+ "target": "es6",
5
+ "moduleResolution": "node",
6
+ "checkJs": true
7
+ },
8
+ "include": [ "index.js", "babble/*.js", "babble/apps/*.js" ],
9
+ "exclude": [ "node_modules" ]
10
+ }
package/lib/call.js CHANGED
@@ -87,6 +87,20 @@ const hangupcodes = {
87
87
  REJECTED: { "reason": "REJECTED", "sip": 608 }
88
88
  }
89
89
 
90
+ /**
91
+ * Ecapsulate a SIP exception
92
+ * @param { object } hangupcode
93
+ * @param { string } message
94
+ */
95
+ class SipError extends Error {
96
+ constructor( hangupcode, message ) {
97
+ super( message )
98
+ this.code = hangupcode.sip
99
+ this.hangupcode = hangupcode
100
+ this.name = "SipError"
101
+ }
102
+ }
103
+
90
104
  /* Reverse codes - include inbound error codes.
91
105
  If not in this list we return REQUEST_TERMINATED during creation */
92
106
  const inboundsiperros = {
@@ -99,19 +113,27 @@ let callmanager = {
99
113
  "options": {}
100
114
  }
101
115
 
102
- /** @class */
116
+ /**
117
+ * @typedef { object } entity
118
+ * @property { string } uri full uri
119
+ * @property { string } [ username ] username part
120
+ * @property { string } [ realm ] realm (domain) part
121
+ * @property { string } [ display ] how the user should be displayed
122
+ * @property { number } [ ccc ] - Current Call Count
123
+ */
124
+
103
125
  class call {
104
126
 
105
127
  /**
106
- Construct our call object with all defaults, including a default UUID.
107
- @constructs call
108
- @hideconstructor
128
+ * Construct our call object with all defaults, including a default UUID.
129
+ * @constructs call
130
+ * @hideconstructor
109
131
  */
110
132
  constructor() {
111
133
  this.uuid = uuidv4()
112
134
 
113
135
  /**
114
- @enum {string} type "uas" | "uac"
136
+ @enum { string } type "uas" | "uac"
115
137
  @summary The type (uac or uas) from our perspective.
116
138
  */
117
139
  this.type = "uac"
@@ -149,7 +171,7 @@ class call {
149
171
  }
150
172
 
151
173
  /**
152
- * @private
174
+ * Protected for this module
153
175
  */
154
176
  this._state = {
155
177
  "_onhangup": false,
@@ -157,42 +179,38 @@ class call {
157
179
  }
158
180
 
159
181
  /**
160
- @member
161
- @summary Channels which have been created
182
+ * @summary Channels which have been created
162
183
  */
163
184
  this.channels = {
164
- "audio": false,
185
+ "audio": undefined,
165
186
  "closed": {
166
187
  "audio": []
167
188
  }
168
189
  }
169
190
 
170
191
  /**
171
- @member
172
- @summary Store our local and remote sdp objects
192
+ * @summary Store our local and remote sdp objects
173
193
  */
174
194
  this.sdp = {
175
- "local": false,
176
- "remote": false
195
+ "local": undefined,
196
+ "remote": undefined
177
197
  }
178
198
 
179
199
  /**
180
- @member
181
- @summary UACs we create
200
+ * @summary UACs we create
182
201
  */
183
202
  this.children = new Set()
184
203
  /**
185
- @member
186
- @summary Who created us
204
+ * @summary Who created us
187
205
  */
188
- this.parent = false
206
+ this.parent = undefined
189
207
 
190
208
  /**
191
- @typedef {Object} epochs
192
- @property {number} startat UNIX timestamp of when the call was started (created)
193
- @property {number} answerat UNIX timestamp of when the call was answered
194
- @property {number} endat UNIX timestamp of when the call ended
195
- */
209
+ * @typedef {Object} epochs
210
+ * @property {number} startat UNIX timestamp of when the call was started (created)
211
+ * @property {number} answerat UNIX timestamp of when the call was answered
212
+ * @property {number} endat UNIX timestamp of when the call ended
213
+ */
196
214
 
197
215
  /** @member {epochs} */
198
216
  this.epochs = {
@@ -203,13 +221,15 @@ class call {
203
221
  }
204
222
 
205
223
  /**
206
- @typedef {Object} sipdialog
207
- @property {object} tags
208
- @property {string} tags.local
209
- @property {string} tags.remote
210
- */
211
- /** @member {sipdialog} */
224
+ * @typedef { object } sipdialog
225
+ * @property { string } callid
226
+ * @property { object } tags
227
+ * @property { string } tags.local
228
+ * @property { string } tags.remote
229
+ */
230
+ /** @member { sipdialog } */
212
231
  this.sip = {
232
+ "callid": undefined,
213
233
  "tags": {
214
234
  "remote": "",
215
235
  "local": ""
@@ -217,32 +237,23 @@ class call {
217
237
  }
218
238
 
219
239
  /**
220
- @typedef { Object } entity
221
- @property { string } [ username ] username part
222
- @property { string } [ realm ] realm (domain) part
223
- @property { string } [ uri ] full uri
224
- @property { string } [ display ] how the user should be displayed
225
- */
226
- /**
227
- For inbound calls - this is discovered by authentication. For outbound
228
- this is requested by the caller - i.e. the destination is the registered user.
229
- @member { _entity }
230
- @private
240
+ * For inbound calls - this is discovered by authentication. For outbound
241
+ * this is requested by the caller - i.e. the destination is the registered user.
242
+ * @type { entity }
243
+ * Protected for this module.
231
244
  */
232
245
  this._entity
233
246
 
234
247
  /**
235
248
  Override caller id or name.
236
- @member { _remote }
237
249
  @private
238
250
  */
239
251
  this._remote = {
240
- "id": false,
241
- "name": false
252
+ "id": undefined,
253
+ "name": undefined
242
254
  }
243
255
 
244
256
  /**
245
- * @member { object }
246
257
  * @summary contains network information regarding call
247
258
  */
248
259
  this.network = {
@@ -254,8 +265,7 @@ class call {
254
265
  }
255
266
 
256
267
  /**
257
- @member {object}
258
- @summary user definable object that allows other modules to store data in this call.
268
+ * @summary user definable object that allows other modules to store data in this call.
259
269
  */
260
270
  this.vars = {}
261
271
 
@@ -266,24 +276,23 @@ class call {
266
276
  this._receivedtelevents = ""
267
277
 
268
278
  /**
269
- @member {object}
270
- @private
279
+ * @private
271
280
  */
272
281
  this._promises = {
273
282
  "resolve": {
274
- "auth": false,
275
- "hangup": false,
276
- "events": false,
277
- "channelevent": false
283
+ "auth": undefined,
284
+ "hangup": undefined,
285
+ "events": undefined,
286
+ "channelevent": undefined
278
287
  },
279
288
  "reject": {
280
- "auth": false,
281
- "channelevent": false
289
+ "auth": undefined,
290
+ "channelevent": undefined
282
291
  },
283
292
  "promise": {
284
- "hangup": false,
285
- "events": false,
286
- "channelevent": false
293
+ "hangup": undefined,
294
+ "events": undefined,
295
+ "channelevent": undefined
287
296
  }
288
297
  }
289
298
 
@@ -292,52 +301,61 @@ class call {
292
301
  } )
293
302
 
294
303
  /**
295
- @member {object}
296
- @private
304
+ * @private
297
305
  */
298
306
  this._timers = {
299
- "auth": false,
300
- "newuac": false,
301
- "events": false,
302
- "seinterval": false,
303
- "anyevent": false
307
+ "auth": undefined,
308
+ "newuac": undefined,
309
+ "events": undefined,
310
+ "seinterval": undefined,
311
+ "anyevent": undefined
304
312
  }
305
313
 
306
314
  /**
307
- @member {object}
308
- @private
315
+ * @private
309
316
  */
310
317
  this._em = new events.EventEmitter()
311
318
 
312
- /* copy default */
319
+ /**
320
+ * @typedef { Object } options
321
+ * @property { string } [ contact ] contact string
322
+ * @property { string } [ preferedcodecs ] as it says
323
+ * @property { boolean } [ rfc2833 ] if set to true enable 2833
324
+ * @property { string } [ display ] how the user should be displayed
325
+ * @property { Array } [ headers ]
326
+ * @property { number } [ uactimeout ] timeout in mS
327
+ * @property { boolean } [ late ] - do we use late negotiation
328
+ * @property { boolean } [ noAck ] do not use - converts our options into Drachtio options
329
+ * @property { string } [ localSdp ] do not use - what we pass into drachtio
330
+ */
331
+ /**
332
+ * copy default
333
+ * @type { options }
334
+ */
313
335
  this.options = { ...callmanager.options }
314
336
 
315
337
  /**
316
- @member
317
- @private
338
+ * @private
318
339
  */
319
340
  this._auth = sipauth.create( callmanager.options.proxy )
320
341
 
321
342
  this.referauthrequired = callmanager.options.referauthrequired
322
343
 
323
344
  /**
324
- Enable access for other modules.
345
+ * Enable access for other modules.
325
346
  */
326
347
  this.hangupcodes = hangupcodes
327
- }
328
348
 
329
- /**
330
- @typedef entity
331
- @property { string } username
332
- @property { string } realm
333
- @property { string } uri
334
- @property { string } display
335
- @property { number } ccc - Current Call Count
336
- */
349
+ /**
350
+ * If the call is referred somewhere, this is the url we use
351
+ * @type { string }
352
+ */
353
+ this.referingtouri
354
+ }
337
355
 
338
356
  /**
339
- Returns the entity if known (i.e. outbound or inbound authed).
340
- @returns { Promise< entity > }
357
+ * Returns the entity if known (i.e. outbound or inbound authed).
358
+ * @returns { Promise< entity > }
341
359
  */
342
360
  get entity() {
343
361
 
@@ -381,7 +399,6 @@ class call {
381
399
  if( !e.uri && !( e.username && e.realm ) ) return
382
400
  this._entity = e
383
401
 
384
- this._entity.name = ""
385
402
  this._entity.display = ""
386
403
 
387
404
  if( this._entity.uri ) {
@@ -408,7 +425,7 @@ class call {
408
425
 
409
426
  /**
410
427
  * Sets caller id
411
- * @param { callerid } rem
428
+ * @param { string } callerid
412
429
  */
413
430
  set callerid( callerid ) {
414
431
  this._remote.id = callerid
@@ -416,7 +433,7 @@ class call {
416
433
 
417
434
  /**
418
435
  * Sets caller id name
419
- * @param { calleridname } rem
436
+ * @param { string } calleridname
420
437
  */
421
438
  set calleridname( calleridname ) {
422
439
  this._remote.name = calleridname
@@ -578,7 +595,7 @@ class call {
578
595
 
579
596
  /**
580
597
  hasmedia
581
- @return {bool} - true if the call has media (i.e. is established on not held).
598
+ @return { boolean } - true if the call has media (i.e. is established on not held).
582
599
  */
583
600
  get hasmedia() {
584
601
  if( this.state.held ) return false
@@ -597,7 +614,7 @@ class call {
597
614
 
598
615
  /**
599
616
  trying
600
- @return {bool} - true if the call has been trying.
617
+ @return { boolean } - true if the call has been trying.
601
618
  */
602
619
  get trying() {
603
620
  return this.state.trying
@@ -605,7 +622,7 @@ class call {
605
622
 
606
623
  /**
607
624
  ringing
608
- @return {bool} - true if the call has been ringing.
625
+ @return { boolean } - true if the call has been ringing.
609
626
  */
610
627
  get ringing() {
611
628
  return this.state.ringing
@@ -620,7 +637,7 @@ class call {
620
637
 
621
638
  /**
622
639
  established - if the call isn't already established then set the answerat time.
623
- @param {bool} s - true if the call has been established.
640
+ @param { boolean } s - true if the call has been established.
624
641
  */
625
642
  set established( s ) {
626
643
  if( this.state.established != s ) {
@@ -631,7 +648,7 @@ class call {
631
648
 
632
649
  /**
633
650
  established
634
- @return {bool} - true if the call has been established.
651
+ @return { boolean } - true if the call has been established.
635
652
  */
636
653
  get established() {
637
654
  return this.state.established
@@ -639,7 +656,7 @@ class call {
639
656
 
640
657
  /**
641
658
  @summary canceled - if the call isn't already canceled then set the endat time.
642
- @type {boolean}
659
+ @type { boolean }
643
660
  */
644
661
  set canceled( s ) {
645
662
  if( this.state.canceled != s ) {
@@ -658,7 +675,7 @@ class call {
658
675
 
659
676
  /**
660
677
  destroyed - if the call isn't already desroyed then set the endat time.
661
- @param {bool} s - true if the call has been destroyed.
678
+ @param { boolean } s - true if the call has been destroyed.
662
679
  */
663
680
  set destroyed( s ) {
664
681
  if( this.state.destroyed != s ) {
@@ -669,7 +686,7 @@ class call {
669
686
 
670
687
  /**
671
688
  destroyed
672
- @return {bool} - true if teh call has been destroyed.
689
+ @return { boolean } - true if teh call has been destroyed.
673
690
  */
674
691
  get destroyed() {
675
692
  return true == this.state.destroyed
@@ -681,7 +698,7 @@ class call {
681
698
 
682
699
  /**
683
700
  @summary the current state of the call as a string: trying|proceeding|early|confirmed|terminated
684
- @return {string}
701
+ @return { string }
685
702
  */
686
703
  get statestr() {
687
704
  if( this.state.established ) {
@@ -705,54 +722,50 @@ class call {
705
722
 
706
723
  /**
707
724
  duration
708
- @return {number} - the number of seconds between now (or endat if ended) and the time the call was started.
725
+ @return { number } - the number of seconds between now (or endat if ended) and the time the call was started.
709
726
  */
710
727
  get duration() {
711
- if( 0 !== this.epochs.endat ) return parseInt( this.epochs.endat - this.epochs.startat )
712
- return parseInt( Math.floor( +new Date() / 1000 ) - this.epochs.startat )
728
+ if( 0 !== this.epochs.endat ) return this.epochs.endat - this.epochs.startat
729
+ return Math.floor( +new Date() / 1000 ) - this.epochs.startat
713
730
  }
714
731
 
715
732
  /**
716
733
  Get the estrablished time.
717
- @return {number} - the number of seconds between now (or endat if ended) and the time the call was answered.
734
+ @return { number } - the number of seconds between now (or endat if ended) and the time the call was answered.
718
735
  */
719
736
  get billingduration() {
720
737
  if( 0 === this.epochs.answerat ) return 0
721
- if( 0 !== this.epochs.endat ) return parseInt( this.epochs.endat - this.epochs.answerat )
722
- return parseInt( Math.floor( +new Date() / 1000 ) - this.epochs.answerat )
738
+ if( 0 !== this.epochs.endat ) return this.epochs.endat - this.epochs.answerat
739
+ return Math.floor( +new Date() / 1000 ) - this.epochs.answerat
723
740
  }
724
741
 
725
- /**
726
- Callback for events we pass back to inerested parties.
727
- @callback call.event
728
- @param {object} call - we pass *this back into the requester
729
- */
730
742
 
731
743
  /**
732
- Registers an event callback for this specific call. An event sink registered
733
- on this member will receive events only for this call. We emit on call specific
734
- emitter and a global emitter.
735
- @param { string } ev - The contact string for registered or other sip contact
736
- @param { call.event } cb
737
- */
744
+ * Callback for events we pass back to inerested parties.
745
+ * Registers an event callback for this specific call. An event sink registered
746
+ * on this member will receive events only for this call. We emit on call specific
747
+ * emitter and a global emitter.
748
+ * @param { string } ev - The contact string for registered or other sip contact
749
+ * @param { (...args: any[] ) => void } cb
750
+ */
738
751
  on( ev, cb ) {
739
752
  this._em.on( ev, cb )
740
753
  }
741
754
 
742
755
  /**
743
- See event emitter once
744
- @param { string } ev - The contact string for registered or other sip contact
745
- @param { call.event } cb
746
- */
756
+ * See event emitter once
757
+ * @param { string } ev - The contact string for registered or other sip contact
758
+ * @param { (...args: any[] ) => void } cb
759
+ */
747
760
  once( ev, cb ) {
748
761
  this._em.once( ev, cb )
749
762
  }
750
763
 
751
764
  /**
752
- See event emitter off
753
- @param { string } ev - The contact string for registered or other sip contact
754
- @param { call.event } cb
755
- */
765
+ * See event emitter off
766
+ * @param { string } ev - The contact string for registered or other sip contact
767
+ * @param { (...args: any[] ) => void } cb
768
+ */
756
769
  off( ev, cb ) {
757
770
  if( !cb ) {
758
771
  this._em.removeAllListeners( ev )
@@ -763,9 +776,9 @@ class call {
763
776
  }
764
777
 
765
778
  /**
766
- See event emitter removeAllListeners
767
- @param { string } ev - The contact string for registered or other sip contact
768
- */
779
+ * See event emitter removeAllListeners
780
+ * @param { string } [ ev ] - The contact string for registered or other sip contact
781
+ */
769
782
  removealllisteners( ev ) {
770
783
  if( !ev ) {
771
784
  const evnames = this._em.eventNames()
@@ -896,7 +909,7 @@ class call {
896
909
  child.parent = false
897
910
  }
898
911
 
899
- this.parent = false
912
+ this.parent = undefined
900
913
  this.children.clear()
901
914
  }
902
915
 
@@ -931,7 +944,7 @@ class call {
931
944
  _onring() {
932
945
  if( this.state.ringing ) return
933
946
  this.state.ringing = true
934
- if( false !== this.parent ) {
947
+ if( undefined !== this.parent ) {
935
948
  this.parent.ring()
936
949
  }
937
950
 
@@ -1134,18 +1147,20 @@ class call {
1134
1147
 
1135
1148
  /**
1136
1149
  Sometimes we don't care who if we are the parent or child - we just want the other party
1137
- @return { object|bool } returns call object or if none false
1150
+ @return { object | boolean } returns call object or if none false
1138
1151
  */
1139
1152
  get other() {
1140
1153
  if( this.parent ) return this.parent
1141
1154
 
1155
+ /* first established */
1142
1156
  for( const child of this.children ) {
1143
1157
  if( child.established ) {
1144
1158
  return child
1145
1159
  }
1146
1160
  }
1147
1161
 
1148
- if( 0 < this.children.length ) return this.children.values().next().value
1162
+ /* or the first */
1163
+ if( 0 < this.children.size ) return this.children.values().next().value
1149
1164
 
1150
1165
  return false
1151
1166
  }
@@ -1172,10 +1187,10 @@ class call {
1172
1187
  }
1173
1188
 
1174
1189
  this._timers.auth = setTimeout( () => {
1175
- this._promises.reject.auth()
1176
- this._promises.resolve.auth = false
1177
- this._promises.reject.auth = false
1178
- this._timers.auth = false
1190
+ this._promises.reject.auth( new SipError( hangupcodes.REQUEST_TIMEOUT, "Auth timed out" ) )
1191
+ this._promises.resolve.auth = undefined
1192
+ this._promises.reject.auth = undefined
1193
+ this._timers.auth = undefined
1179
1194
 
1180
1195
  this.hangup( hangupcodes.REQUEST_TIMEOUT )
1181
1196
 
@@ -1206,7 +1221,7 @@ class call {
1206
1221
  this._req = req
1207
1222
  this._res = res
1208
1223
 
1209
- req.on( "cancel", ( req ) => this._oncanceled( req ) )
1224
+ req.on( "cancel", ( /*req*/ ) => this._oncanceled( /*req*/ ) )
1210
1225
 
1211
1226
  if( !this._auth.has( this._req ) ) return false
1212
1227
 
@@ -1230,14 +1245,14 @@ class call {
1230
1245
 
1231
1246
  await this.hangup( hangupcodes.FORBIDDEN )
1232
1247
 
1233
- const r = this._promises.reject.auth
1234
- this._promises.resolve.auth = false
1235
- this._promises.reject.auth = false
1248
+ const reject = this._promises.reject.auth
1249
+ this._promises.resolve.auth = undefined
1250
+ this._promises.reject.auth = undefined
1236
1251
 
1237
1252
  clearTimeout( this._timers.auth )
1238
- this._timers.auth = false
1253
+ this._timers.auth = undefined
1239
1254
 
1240
- if( r ) r()
1255
+ if( reject ) reject( new SipError( hangupcodes.FORBIDDEN, "Bad Auth" ))
1241
1256
 
1242
1257
  return false
1243
1258
  }
@@ -1255,11 +1270,11 @@ class call {
1255
1270
  this.state.authed = true
1256
1271
  await callstore.set( this )
1257
1272
 
1258
- const r = this._promises.resolve.auth
1259
- this._promises.resolve.auth = false
1260
- this._promises.reject.auth = false
1261
- this._timers.auth = false
1262
- if( r ) r()
1273
+ const resolve = this._promises.resolve.auth
1274
+ this._promises.resolve.auth = undefined
1275
+ this._promises.reject.auth = undefined
1276
+ this._timers.auth = undefined
1277
+ if( resolve ) resolve()
1263
1278
 
1264
1279
  this._em.emit( "call.authed", this )
1265
1280
  callmanager.options.em.emit( "call.authed", this )
@@ -1298,14 +1313,14 @@ class call {
1298
1313
  if( this._promises.resolve.events ) {
1299
1314
  const r = this._promises.resolve.events
1300
1315
 
1301
- this._promises.resolve.events = false
1302
- this._promises.promise.events = false
1316
+ this._promises.resolve.events = undefined
1317
+ this._promises.promise.events = undefined
1303
1318
  r( ourmatch[ 0 ] )
1304
1319
  }
1305
1320
 
1306
1321
  if( this._timers.events ) {
1307
1322
  clearTimeout( this._timers.events )
1308
- this._timers.events = false
1323
+ this._timers.events = undefined
1309
1324
  }
1310
1325
  }
1311
1326
  }
@@ -1313,9 +1328,9 @@ class call {
1313
1328
 
1314
1329
  /**
1315
1330
  Called by our call plan to wait for events for auto attendant/IVR.
1316
- @param {string} [match] - reg exp matching what is required from the user.
1317
- @param {Int} [timeout] - time to wait before giving up.
1318
- @return {Promise} - the promise either resolves to a string if it matches or undefined if it times out..
1331
+ @param { string | RegExp } [match] - reg exp matching what is required from the user.
1332
+ @param { number } [timeout] - time to wait before giving up.
1333
+ @return { Promise } - the promise either resolves to a string if it matches or undefined if it times out..
1319
1334
  */
1320
1335
  waitfortelevents( match = /[0-9A-D*#]/, timeout = 30000 ) {
1321
1336
 
@@ -1330,9 +1345,9 @@ class call {
1330
1345
  this._promises.resolve.events()
1331
1346
  }
1332
1347
 
1333
- this._promises.resolve.events = false
1334
- this._promises.promise.events = false
1335
- this._timers.events = false
1348
+ this._promises.resolve.events = undefined
1349
+ this._promises.promise.events = undefined
1350
+ this._timers.events = undefined
1336
1351
  delete this.eventmatch
1337
1352
 
1338
1353
  }, timeout )
@@ -1417,7 +1432,7 @@ class call {
1417
1432
  /* we have already opened a channel (probably early now answering) */
1418
1433
  this.channels.audio.remote( channeldef.remote )
1419
1434
  } else {
1420
-
1435
+
1421
1436
  await this.#openrelatedchannel( channeldef )
1422
1437
 
1423
1438
  this.sdp.local = sdpgen.create()
@@ -1437,10 +1452,12 @@ class call {
1437
1452
  }
1438
1453
 
1439
1454
  /**
1440
- *
1455
+ * @param { object } preferredcall - allow to specify a, not necessarily related call,
1456
+ * that can be used to open the new channel's node.
1457
+ *
1441
1458
  * @returns { Promise }
1442
1459
  */
1443
- async #choosecodecforanswer() {
1460
+ async #choosecodecforanswer( preferredcall = undefined ) {
1444
1461
  if( this._req.msg && this._req.msg.body ) {
1445
1462
  this.selectedcodec = this.sdp.remote.intersection( this.options.preferedcodecs, true )
1446
1463
  if( !this.selectedcodec ) {
@@ -1467,6 +1484,8 @@ class call {
1467
1484
  channeldef.remote.icepwd = this.sdp.remote.sdp.media[ 0 ].icePwd
1468
1485
  }
1469
1486
 
1487
+ channeldef.preferredcall = preferredcall
1488
+
1470
1489
  /* We might have already opened our audio when we received 183 (early). */
1471
1490
  await this.#openchannelsforanswer( channeldef )
1472
1491
  }
@@ -1474,16 +1493,18 @@ class call {
1474
1493
 
1475
1494
  /**
1476
1495
  * Answer this (inbound) call and store a channel which can be used. This framework will catch and cleanup this call if this is rejected.
1477
- * @param { object } options
1478
- * @param { boolean } options.early - don't answer the channel (establish) but establish early media (respond to 183).
1496
+ * @param { object } [ options ]
1497
+ * @param { boolean } [ options.early ] - don't answer the channel (establish) but establish early media (respond to 183).
1498
+ * @param { object } [ options.preferredcall ]
1479
1499
  *
1480
1500
  * @return {Promise} Returns a promise which resolves if the call is answered, otherwise rejects the promise.
1481
1501
  */
1482
- async answer( options = {} ) {
1502
+ async answer( options = { early: false, preferredcall: undefined } ) {
1483
1503
 
1484
1504
  if( this.canceled || this.established ) return
1485
1505
 
1486
- await this.#choosecodecforanswer()
1506
+ await this.#choosecodecforanswer( options.preferredcall )
1507
+
1487
1508
  if( this.canceled ) return
1488
1509
 
1489
1510
  if( options.early ) {
@@ -1555,12 +1576,12 @@ class call {
1555
1576
  */
1556
1577
 
1557
1578
  if( this._timers.anyevent ) clearTimeout( this._timers.anyevent )
1558
- this._timers.anyevent = false
1579
+ this._timers.anyevent = undefined
1559
1580
 
1560
1581
  const r = this._promises.resolve.channelevent
1561
- this._promises.resolve.channelevent = false
1562
- this._promises.reject.channelevent = false
1563
- this._promises.promise.channelevent = false
1582
+ this._promises.resolve.channelevent = undefined
1583
+ this._promises.reject.channelevent = undefined
1584
+ this._promises.promise.channelevent = undefined
1564
1585
  if( r ) r( e )
1565
1586
  }
1566
1587
 
@@ -1597,7 +1618,7 @@ class call {
1597
1618
 
1598
1619
  A telephone event will resolve this promise as we typically need speech to be interupted
1599
1620
  by the user. Note, peeking a telephone-event (i.e. DTMF) will not clear it like waitfortelevents will.
1600
- @param { regex } constraints - event to filter for from our RTP server - excluding DTMF events - these will always return
1621
+ @param { object } constraints - event to filter for from our RTP server - excluding DTMF events - these will always return
1601
1622
  */
1602
1623
  waitforanyevent( constraints, timeout = 500 ) {
1603
1624
 
@@ -1613,9 +1634,9 @@ class call {
1613
1634
 
1614
1635
  this._timers.anyevent = setTimeout( () => {
1615
1636
  const r = this._promises.resolve.channelevent
1616
- this._promises.promise.channelevent = false
1617
- this._promises.resolve.channelevent = false
1618
- this._promises.reject.channelevent = false
1637
+ this._promises.promise.channelevent = undefined
1638
+ this._promises.resolve.channelevent = undefined
1639
+ this._promises.reject.channelevent = undefined
1619
1640
  if( r ) r( "timeout" )
1620
1641
  }, timeout * 1000 )
1621
1642
 
@@ -2195,8 +2216,8 @@ class call {
2195
2216
  @param { string } address - remote address (ip)
2196
2217
  @param { number } port - remote port
2197
2218
  @param { number } codec
2198
- @param { string } fingerprint - remote sha 256 fingerprint
2199
- @param { string } mode - "active"|"passive"
2219
+ @param { string } [ fingerprint ] - remote sha 256 fingerprint
2220
+ @param { string } [ mode ] - "active"|"passive"
2200
2221
  */
2201
2222
  static _createchannelremotedef( address, port, codec, fingerprint, mode /* active|passive */ ) {
2202
2223
  const chandef = {
@@ -2220,6 +2241,8 @@ class call {
2220
2241
 
2221
2242
  /**
2222
2243
  Sets our hangup cause correctly - if not already set.
2244
+ @param { string } src
2245
+ @param { object } [ reason ]
2223
2246
  @private
2224
2247
  */
2225
2248
  _sethangupcause( src, reason ) {
@@ -2250,24 +2273,24 @@ class call {
2250
2273
  /* Clean up promises (ensure they are resolved) and clear any timers */
2251
2274
  for ( const [ key, value ] of Object.entries( this._timers ) ) {
2252
2275
  if( value ) clearTimeout( value )
2253
- this._timers[ key ] = false
2276
+ this._timers[ key ] = undefined
2254
2277
  }
2255
2278
 
2256
2279
  const authreject = this._promises.reject.auth
2257
- this._promises.reject.auth = false
2258
- this._promises.resolve.auth = false
2259
- if( authreject ) authreject( this )
2280
+ this._promises.reject.auth = undefined
2281
+ this._promises.resolve.auth = undefined
2282
+ if( authreject ) authreject( new SipError( hangupcodes.REQUEST_TIMEOUT, "Auth timed out (cleanup)" ) )
2260
2283
 
2261
2284
  const chanev = this._promises.reject.channelevent
2262
- this._promises.resolve.channelevent = false
2263
- this._promises.reject.channelevent = false
2264
- this._promises.promise.channelevent = false
2285
+ this._promises.resolve.channelevent = undefined
2286
+ this._promises.reject.channelevent = undefined
2287
+ this._promises.promise.channelevent = undefined
2265
2288
  if( chanev ) chanev( Error( "Call hungup" ) )
2266
2289
 
2267
2290
  const resolves = []
2268
2291
  for ( const [ key, value ] of Object.entries( this._promises.resolve ) ) {
2269
2292
  if( value ) resolves.push( value )
2270
- this._promises.resolve[ key ] = false
2293
+ this._promises.resolve[ key ] = undefined
2271
2294
  }
2272
2295
 
2273
2296
  /* Call outstanding resolves for promises - this will trigger out hangup promise also */
@@ -2286,8 +2309,8 @@ class call {
2286
2309
  * Used by our frame to a) continue a hangup which has been initiated by either us or the network.
2287
2310
  * Complete the hangup, including hanging up all children and waiting for them to complete their
2288
2311
  * hangup.
2289
- * @param {string} [us] - "us"|"wire"
2290
- * @param {object} reason - one of the reasons from the hangupcodes enum - only used if we havn't alread set our reason
2312
+ * @param { string } [ src ] - "us"|"wire"
2313
+ * @param { object } [ reason ] - one of the reasons from the hangupcodes enum - only used if we havn't alread set our reason
2291
2314
  * @private
2292
2315
  */
2293
2316
  async _onhangup( src = "us", reason ) {
@@ -2377,16 +2400,16 @@ class call {
2377
2400
  }
2378
2401
 
2379
2402
  await this._promises.promise.hangup
2380
- this._promises.promise.hangup = false
2381
- this._promises.resolve.hangup = false
2403
+ this._promises.promise.hangup = undefined
2404
+ this._promises.resolve.hangup = undefined
2382
2405
 
2383
2406
  }
2384
2407
 
2385
2408
  /**
2386
- Send an UPDATE. Use to updated called id, caller id, sdp etc. Send in dialog - TODO look how to send
2387
- early as this is recomended in the RFC.
2388
- @param { Object } options
2389
- @param { remoteid } [ options.remote ] - if present update the remote called/caller id (display) - if not will get from other
2409
+ * Send an UPDATE. Use to updated called id, caller id, sdp etc. Send in dialog - TODO look how to send
2410
+ * early as this is recomended in the RFC.
2411
+ * @param { object } options
2412
+ * @param { entity } options.remote
2390
2413
  */
2391
2414
  async update( options ) {
2392
2415
 
@@ -2454,19 +2477,23 @@ class call {
2454
2477
  @summary Creates a new SIP dialog. Returns a promise which resolves
2455
2478
  when the dialog is either answered (or cancelled for some reason).
2456
2479
  The promise resolves to a new call is one is generated, or undefined if not.
2457
- @param { Object } [ options ] - Options object. See default_options in index.js for more details.
2480
+ @param { object } [ options ] - Options object. See default_options in index.js for more details.
2458
2481
  @param { string } [ options.contact ] - The contact string
2459
2482
  @param { boolean } [ options.orphan ] - If present and true then orphan the new call
2483
+ @param { object } [ options.auth ]
2460
2484
  @param { string } [ options.auth.username ] - If SIP auth required username
2461
2485
  @param { string } [ options.auth.password ] - If SIP auth required password
2462
2486
  @param { object } [ options.headers ] - Object containing extra sip headers required.
2463
2487
  @param { object } [ options.uactimeout ] - override the deault timeout
2464
2488
  @param { boolean } [ options.late ] - late negotiation
2465
2489
  @param { entity } [ options.entity ] - used to store this call against and look up a contact string if not supplied.
2490
+ @param { object } [ options.entity ]
2466
2491
  @param { string } [ options.entity.username ]
2467
2492
  @param { string } [ options.entity.realm ]
2468
2493
  @param { string } [ options.entity.uri ]
2469
2494
  @param { number } [ options.entity.max ] - if included no more than this number of calls for this entity (only if we look user up)
2495
+ @param { object } [ options.parent ] - the call we wish to become parent
2496
+ @param { object } [ options.preferredcall ] another related call which we may want to use the rtp host on
2470
2497
  @param { object } [ callbacks ]
2471
2498
  @param { earlycallback } [ callbacks.early ] - callback to provide a call object with early call (pre dialog)
2472
2499
  @param { confirmcallback } [ callbacks.confirm ] - called when a dialog is confirmed but before it is bridged with a parent - this provides an opportunity for another call to adopt this call
@@ -2488,10 +2515,13 @@ class call {
2488
2515
 
2489
2516
  options.headers[ "Max-Forwards" ] = maxforwards
2490
2517
 
2491
- if( !options.orphan ) {
2518
+ if( !options.orphan && !options.parent ) {
2492
2519
  options.parent = this
2520
+
2521
+ if ( !options.preferredcall )
2522
+ options.preferredcall = options.parent.channels.audio
2493
2523
  }
2494
-
2524
+
2495
2525
  return await call.newuac( options, callbacks )
2496
2526
  }
2497
2527
 
@@ -2600,13 +2630,17 @@ class call {
2600
2630
  * @param { object } [ channeldef ]
2601
2631
  */
2602
2632
  async #openrelatedchannel( channeldef ) {
2603
-
2604
2633
  const relatedcall = this.other
2605
- if( relatedcall && relatedcall.channels.audio )
2606
- this.channels.audio = await relatedcall.channels.audio.openchannel( channeldef, this._handlechannelevents.bind( this ) )
2607
- else
2634
+ /* TODO: this is a hack. projectrtp has become too complicated with both a listen and connect
2635
+ mechanism. This is causing problems in code like this. There is no interface to
2636
+ detect which mode the channel is in - but the channels property will exist on a connect
2637
+ style channel. projectrtp will get a rewrite to support only one. */
2638
+ if( relatedcall && relatedcall.channels.audio && relatedcall.channels.audio.channels )
2639
+ this.channels.audio = await this.other.channels.audio.openchannel( channeldef, this._handlechannelevents.bind( this ) )
2640
+ else if ( channeldef && channeldef.preferredcall && channeldef.preferredcall.channels && channeldef.preferredcall.channels.audio )
2641
+ this.channels.audio = await channeldef.preferredcall.channels.audio.openchannel( channeldef, this._handlechannelevents.bind( this ) )
2642
+ else
2608
2643
  this.channels.audio = await projectrtp.openchannel( channeldef, this._handlechannelevents.bind( this ) )
2609
-
2610
2644
  }
2611
2645
 
2612
2646
  /**
@@ -2626,12 +2660,12 @@ class call {
2626
2660
  /**
2627
2661
  *
2628
2662
  */
2629
- async #openchannelsfornewuac() {
2663
+ async #openchannelsfornewuac( channeldef = undefined ) {
2630
2664
  if( this.options.late ) {
2631
2665
  this.options.noAck = true /* this is a MUST for late negotiation */
2632
2666
  } else {
2633
2667
 
2634
- await this.#openrelatedchannel()
2668
+ await this.#openrelatedchannel( channeldef )
2635
2669
 
2636
2670
  this.sdp.local = sdpgen.create().addcodecs( this.options.preferedcodecs )
2637
2671
  this.sdp.local.setaudioport( this.channels.audio.local.port )
@@ -2785,6 +2819,7 @@ class call {
2785
2819
  @param { object } [ options ] - Options object. See default_options in index.js for more details.
2786
2820
  @param { call } [ options.parent ] - the parent call object
2787
2821
  @param { string } [ options.contact ] - The contact string
2822
+ @param { object } [ options.auth ]
2788
2823
  @param { string } [ options.auth.username ] - If SIP auth required username
2789
2824
  @param { string } [ options.auth.password ] - If SIP auth required password
2790
2825
  @param { object } [ options.headers ] - Object containing extra sip headers required.
@@ -2793,6 +2828,7 @@ class call {
2793
2828
  @param { boolean } [ options.late ] - late negotiation
2794
2829
  @param { boolean } [ options.privacy ] - sets the privacy
2795
2830
  @param { entity } [ options.entity ] - used to store this call against and look up a contact string if not supplied.
2831
+ @param { object } [ options.entity ]}
2796
2832
  @param { string } [ options.entity.username ]
2797
2833
  @param { string } [ options.entity.realm ]
2798
2834
  @param { string } [ options.entity.uri ]
@@ -2801,6 +2837,7 @@ class call {
2801
2837
  @param { object } [ options.callerid ]
2802
2838
  @param { string } [ options.callerid.number ]
2803
2839
  @param { string } [ options.callerid.name ]
2840
+ @param { object } [ options.preferredcall ] another related call which we may want to use the rtp host on
2804
2841
  @param { object } [ callbacks ]
2805
2842
  @param { earlycallback } [ callbacks.early ] - callback to provide a call object with early call (pre dialog)
2806
2843
  @param { confirmcallback } [ callbacks.confirm ] - called when a dialog is confirmed but before it is bridged with a parent - this provides an opportunity for another call to adopt this call
@@ -2849,7 +2886,7 @@ class call {
2849
2886
  newcall.options.headers = tmpheaders
2850
2887
 
2851
2888
  newcall.#confignetwork( options )
2852
- await newcall.#openchannelsfornewuac()
2889
+ await newcall.#openchannelsfornewuac( { "preferredcall" : options.preferredcall } )
2853
2890
 
2854
2891
  let newdialog
2855
2892
  try {
@@ -2926,7 +2963,7 @@ class call {
2926
2963
  */
2927
2964
  #setdialog( d ) {
2928
2965
  clearTimeout( this._timers.newuac )
2929
- this._timers.newuac = false
2966
+ this._timers.newuac = undefined
2930
2967
 
2931
2968
  if( this.destroyedcancelledorhungup ) return
2932
2969
 
@@ -2962,7 +2999,7 @@ class call {
2962
2999
  Create a new object when we receive an INVITE request.
2963
3000
 
2964
3001
  @param { object } req - req object from drachtio
2965
- @param { res } res - res object from drachtio
3002
+ @param { object } res - res object from drachtio
2966
3003
  @returns { Promise< call > }
2967
3004
  */
2968
3005
  static async frominvite( req, res ) {
@@ -2990,7 +3027,7 @@ class call {
2990
3027
  @private
2991
3028
  */
2992
3029
  c._req = req
2993
- c._req.on( "cancel", ( req ) => c._oncanceled( req ) )
3030
+ c._req.on( "cancel", ( /*req*/ ) => c._oncanceled( /*req*/ ) )
2994
3031
 
2995
3032
  /**
2996
3033
  @member
@@ -3024,13 +3061,11 @@ class call {
3024
3061
  */
3025
3062
  set uactimeout( ms ) {
3026
3063
  if( this.established ) return
3027
- const msi = parseInt( ms )
3028
- if( isNaN( msi ) ) return
3029
3064
 
3030
3065
  clearTimeout( this._timers.newuac )
3031
3066
  this._timers.newuac = setTimeout( () => {
3032
3067
  this.hangup( hangupcodes.REQUEST_TIMEOUT )
3033
- }, msi )
3068
+ }, ms )
3034
3069
  }
3035
3070
  }
3036
3071
 
@@ -15,7 +15,6 @@ class callmanager {
15
15
  @param {object} options
16
16
  */
17
17
  constructor( options ) {
18
- this.onnewcall = false
19
18
  this.options = options
20
19
 
21
20
  if( undefined === this.options.em ) {
@@ -55,12 +54,16 @@ class callmanager {
55
54
  } catch( e ) {
56
55
  console.error( e )
57
56
  }
58
-
59
57
 
60
- if( false !== this.onnewcall ) {
58
+ if( this.onnewcall ) {
61
59
  try {
62
60
  await this.onnewcall( c )
63
61
  } catch( e ) {
62
+ /* auth failed or timed out excluded as this is noral(ish) */
63
+ if( 403 === e.code ) return
64
+ if( 408 === e.code ) return
65
+
66
+ console.trace( e )
64
67
  c.hangup( this.hangupcodes.SERVER_ERROR )
65
68
  }
66
69
  }
@@ -108,13 +111,14 @@ class callmanager {
108
111
  Is configured to use drachtio and registers emitter for presence.
109
112
  @return {callmanager}
110
113
  */
111
- let cm = false
114
+ let cm
112
115
  module.exports.callmanager = ( options ) => {
113
- if( false !== cm ) return cm
116
+ if( cm ) return cm
114
117
 
115
118
  assert( undefined !== options.srf )
116
119
  cm = new callmanager( options )
117
120
  call.setcallmanager( cm )
121
+ // @ts-ignore
118
122
  cm._use()
119
123
  return cm
120
124
  }
package/lib/sdp.js CHANGED
@@ -82,8 +82,8 @@ const defaultaudiomedia = {
82
82
 
83
83
  /**
84
84
  * Takes a mixed input and outputs an array in the form [ "pcmu", "pcma" ]
85
- * @param { string | array<string|number> } codecarray
86
- * @return { array< string >}
85
+ * @param { string | Array<string|number> } codecarray
86
+ * @return { Array< string >}
87
87
  */
88
88
  function alltocodecname( codecarray ) {
89
89
 
package/lib/store.js CHANGED
@@ -12,11 +12,6 @@ let storebyrealm = new Map()
12
12
  * @param {string} c.uuid - uuid of the call
13
13
  * @param {object} c.sip
14
14
  * @param {string} c.sip.callid - the call id string
15
- * @param {object} c.sip.tags - the local and remote tags
16
- * @param {string} c.sip.tags.local - the local tag
17
- * @param {string} c.sip.tags.remote - the remote tag
18
- * @param {object} c.entity - entity object
19
- * @param {object} c.entity.uri
20
15
  */
21
16
  function iscallobjectgood( c ) {
22
17
  if( "object" !== typeof c ) return false
@@ -67,8 +62,11 @@ function deletefromcallidset( c ) {
67
62
 
68
63
  /**
69
64
  *
70
- * @param { object } c
65
+ * @param { object } c
71
66
  * @param { object } c._entity
67
+ * @param { object } [ c._entity.uri ]
68
+ * @param { object } [ c._entity.username ]
69
+ * @param { object } [ c._entity.realm ]
72
70
  * @return { object | boolean } returns boolean if no further processing or entity object
73
71
  */
74
72
  function fixentity( c ) {
@@ -94,20 +92,21 @@ function fixentity( c ) {
94
92
  /**
95
93
  * This can be called multiple times for the same call to store or update. Stores a
96
94
  * call object in our store.
97
- * @param {object} c - our call object.
98
- * @param {string} c.uuid - uuid of the call
99
- * @param {object} c.sip
100
- * @param {string} c.sip.callid - the call id string
101
- * @param {object} c.sip.tags - the local and remote tags
102
- * @param {string} c.sip.tags.local - the local tag
103
- * @param {string} c.sip.tags.remote - the remote tag
104
- * @param {object} c.entity - entity object
105
- * @param {object} c.entity.uri
106
- * @param {object} c._entity
107
- * @param {object} c.destination
108
- * @param {object} [ c._state ]
109
- * @param {boolean} [ c._state._hangup ]
110
- * @return {Promise} - which resolves on completion (for future in case we support redis or similar)
95
+ * @param { object } c - our call object.
96
+ * @param { string } c.uuid - uuid of the call
97
+ * @param { object } c.sip
98
+ * @param { string } c.sip.callid - the call id string
99
+ * @param { object } c.sip.tags - the local and remote tags
100
+ * @param { string } c.sip.tags.local - the local tag
101
+ * @param { string } c.sip.tags.remote - the remote tag
102
+ * @param { object } c._entity
103
+ * @param { object } [ c._entity.uri ]
104
+ * @param { object } [ c._entity.username ]
105
+ * @param { object } [ c._entity.realm ]
106
+ * @param { object } c.destination
107
+ * @param { object } [ c._state ]
108
+ * @param { boolean } [ c._state._hangup ]
109
+ * @return { Promise } - which resolves on completion (for future in case we support redis or similar)
111
110
  */
112
111
  module.exports.set = async ( c ) => {
113
112
  if( !iscallobjectgood( c ) ) return false
@@ -163,13 +162,14 @@ module.exports.getbyentity = async ( uri ) => {
163
162
  * @param {string} realm - the entity realm
164
163
  * @return {Promise} which resolves to either a set containing calls for this entity or undefined
165
164
  */
166
- module.exports.getbyrealm = async ( realm ) => {
165
+ async function getbyrealm( realm ) {
167
166
  if( !storebyrealm.has( realm ) ) return false
168
167
  return storebyrealm.get( realm )
169
168
  }
170
169
 
171
170
  /* backwards compat - is now realm more generally */
172
- module.exports.getbyentityrealm = module.exports.getbyrealm
171
+ module.exports.getbyrealm = getbyrealm
172
+ module.exports.getbyentityrealm = getbyrealm
173
173
 
174
174
  /**
175
175
  * Returns a unique call by call id and sip tags.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@babblevoice/babble-drachtio-callmanager",
3
- "version": "2.3.8",
3
+ "version": "2.3.9",
4
4
  "description": "Call processing to create a PBX",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -28,10 +28,15 @@
28
28
  "@babblevoice/projectrtp": "^2.3.7"
29
29
  },
30
30
  "devDependencies": {
31
- "chai": "^4.3.4",
32
- "eslint": "^8.42.0",
31
+ "@typescript-eslint/eslint-plugin": "^5.48.2",
32
+ "eslint": "^8.32.0",
33
+ "eslint-config-standard-with-typescript": "^30.0.0",
34
+ "eslint-plugin-import": "^2.27.5",
35
+ "eslint-plugin-n": "^15.6.1",
33
36
  "eslint-plugin-promise": "^6.1.1",
34
- "mocha": "^9.2.2"
37
+ "mocha": "^9.2.2",
38
+ "chai": "^4.3.6",
39
+ "typescript": "^4.9.4"
35
40
  },
36
41
  "bugs": {
37
42
  "url": "https://github.com/tinpotnick/babble-drachtio-callmanager/issues"
@@ -70,7 +70,7 @@ describe( "call object", function() {
70
70
  expect( call.state ).to.have.property( "destroyed" ).that.is.a( "boolean" ).to.be.true
71
71
 
72
72
  expect( call ).to.have.property( "children" ) // Set - how do you test?
73
- expect( call ).to.have.property( "parent" ).that.is.a( "boolean" ).to.be.false
73
+ expect( call ).to.have.property( "parent" ).that.is.undefined
74
74
 
75
75
  expect( call ).to.have.property( "vars" ).that.is.a( "object" )
76
76
 
@@ -80,7 +80,7 @@ describe( "call object", function() {
80
80
  expect( call.epochs ).to.have.property( "endat" ).that.is.a( "number" )
81
81
 
82
82
  expect( call ).to.have.property( "channels" ).that.is.a( "object" )
83
- expect( call.channels ).to.have.property( "audio" ).to.be.false
83
+ expect( call.channels ).to.have.property( "audio" ).to.be.undefined
84
84
 
85
85
  /* if uas */
86
86
  expect( call ).to.have.property( "network" ).that.is.a( "object" )
@@ -577,7 +577,7 @@ describe( "call object", function() {
577
577
  srfscenario.inbound()
578
578
  } )
579
579
 
580
- c.on( "call.destroyed", ( c ) => {
580
+ c.on( "call.destroyed", ( /*c*/ ) => {
581
581
  eventhappened = true
582
582
  } )
583
583
 
@@ -597,7 +597,7 @@ describe( "call object", function() {
597
597
  eventhappened = true
598
598
  } )
599
599
 
600
- srfscenario.options.em.on( "call.destroyed", ( c ) => {
600
+ srfscenario.options.em.on( "call.destroyed", ( /*c*/ ) => {
601
601
  eventhappened = false
602
602
  } )
603
603
 
@@ -650,7 +650,7 @@ describe( "call object", function() {
650
650
  c._req.msg.uri = "sip:bob@biloxi.com"
651
651
  c._req.setparsedheader( "from", { "params": { "tag": "767sf76wew" }, "uri": "sip:bob@biloxi.com", "host": "biloxi.com" } )
652
652
 
653
- c._res.onsend( ( code, msg ) => {
653
+ c._res.onsend( ( code, /*msg*/ ) => {
654
654
 
655
655
  if( 407 == code ) {
656
656
 
@@ -773,7 +773,7 @@ describe( "call object", function() {
773
773
  const srfscenario = new srf.srfscenario( {} )
774
774
 
775
775
  let createuacoptions
776
- srfscenario.oncreateUAC( ( contact, options, callbacks ) => {
776
+ srfscenario.oncreateUAC( ( contact, options, /*callbacks*/ ) => {
777
777
  createuacoptions = options
778
778
 
779
779
  } )
@@ -798,7 +798,7 @@ describe( "call object", function() {
798
798
  }
799
799
 
800
800
  let earlycallbackcalled = false
801
- const c = await call.newuac( options, { "early": ( c ) => earlycallbackcalled = true } )
801
+ const c = await call.newuac( options, { "early": ( /*c*/ ) => earlycallbackcalled = true } )
802
802
 
803
803
  c.hangup()
804
804
 
@@ -814,7 +814,7 @@ describe( "call object", function() {
814
814
  }
815
815
 
816
816
  let earlycallbackcalled = false
817
- const c = await call.newuac( options, { "confirm": ( c ) => earlycallbackcalled = true } )
817
+ const c = await call.newuac( options, { "confirm": ( /*c*/ ) => earlycallbackcalled = true } )
818
818
 
819
819
  c.hangup()
820
820