@babblevoice/babble-drachtio-callmanager 2.3.7 → 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,6 +1221,8 @@ class call {
1206
1221
  this._req = req
1207
1222
  this._res = res
1208
1223
 
1224
+ req.on( "cancel", ( /*req*/ ) => this._oncanceled( /*req*/ ) )
1225
+
1209
1226
  if( !this._auth.has( this._req ) ) return false
1210
1227
 
1211
1228
  const authorization = this._auth.parseauthheaders( this._req )
@@ -1228,14 +1245,14 @@ class call {
1228
1245
 
1229
1246
  await this.hangup( hangupcodes.FORBIDDEN )
1230
1247
 
1231
- const r = this._promises.reject.auth
1232
- this._promises.resolve.auth = false
1233
- this._promises.reject.auth = false
1248
+ const reject = this._promises.reject.auth
1249
+ this._promises.resolve.auth = undefined
1250
+ this._promises.reject.auth = undefined
1234
1251
 
1235
1252
  clearTimeout( this._timers.auth )
1236
- this._timers.auth = false
1253
+ this._timers.auth = undefined
1237
1254
 
1238
- if( r ) r()
1255
+ if( reject ) reject( new SipError( hangupcodes.FORBIDDEN, "Bad Auth" ))
1239
1256
 
1240
1257
  return false
1241
1258
  }
@@ -1253,11 +1270,11 @@ class call {
1253
1270
  this.state.authed = true
1254
1271
  await callstore.set( this )
1255
1272
 
1256
- const r = this._promises.resolve.auth
1257
- this._promises.resolve.auth = false
1258
- this._promises.reject.auth = false
1259
- this._timers.auth = false
1260
- 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()
1261
1278
 
1262
1279
  this._em.emit( "call.authed", this )
1263
1280
  callmanager.options.em.emit( "call.authed", this )
@@ -1273,7 +1290,7 @@ class call {
1273
1290
  this.canceled = true
1274
1291
 
1275
1292
  for( const child of this.children ) {
1276
- child.hangup()
1293
+ child.hangup( hangupcodes.ORIGINATOR_CANCEL )
1277
1294
  }
1278
1295
 
1279
1296
  this._onhangup( "wire", hangupcodes.ORIGINATOR_CANCEL )
@@ -1296,14 +1313,14 @@ class call {
1296
1313
  if( this._promises.resolve.events ) {
1297
1314
  const r = this._promises.resolve.events
1298
1315
 
1299
- this._promises.resolve.events = false
1300
- this._promises.promise.events = false
1316
+ this._promises.resolve.events = undefined
1317
+ this._promises.promise.events = undefined
1301
1318
  r( ourmatch[ 0 ] )
1302
1319
  }
1303
1320
 
1304
1321
  if( this._timers.events ) {
1305
1322
  clearTimeout( this._timers.events )
1306
- this._timers.events = false
1323
+ this._timers.events = undefined
1307
1324
  }
1308
1325
  }
1309
1326
  }
@@ -1311,9 +1328,9 @@ class call {
1311
1328
 
1312
1329
  /**
1313
1330
  Called by our call plan to wait for events for auto attendant/IVR.
1314
- @param {string} [match] - reg exp matching what is required from the user.
1315
- @param {Int} [timeout] - time to wait before giving up.
1316
- @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..
1317
1334
  */
1318
1335
  waitfortelevents( match = /[0-9A-D*#]/, timeout = 30000 ) {
1319
1336
 
@@ -1328,9 +1345,9 @@ class call {
1328
1345
  this._promises.resolve.events()
1329
1346
  }
1330
1347
 
1331
- this._promises.resolve.events = false
1332
- this._promises.promise.events = false
1333
- this._timers.events = false
1348
+ this._promises.resolve.events = undefined
1349
+ this._promises.promise.events = undefined
1350
+ this._timers.events = undefined
1334
1351
  delete this.eventmatch
1335
1352
 
1336
1353
  }, timeout )
@@ -1415,7 +1432,7 @@ class call {
1415
1432
  /* we have already opened a channel (probably early now answering) */
1416
1433
  this.channels.audio.remote( channeldef.remote )
1417
1434
  } else {
1418
-
1435
+
1419
1436
  await this.#openrelatedchannel( channeldef )
1420
1437
 
1421
1438
  this.sdp.local = sdpgen.create()
@@ -1435,10 +1452,12 @@ class call {
1435
1452
  }
1436
1453
 
1437
1454
  /**
1438
- *
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
+ *
1439
1458
  * @returns { Promise }
1440
1459
  */
1441
- async #choosecodecforanswer() {
1460
+ async #choosecodecforanswer( preferredcall = undefined ) {
1442
1461
  if( this._req.msg && this._req.msg.body ) {
1443
1462
  this.selectedcodec = this.sdp.remote.intersection( this.options.preferedcodecs, true )
1444
1463
  if( !this.selectedcodec ) {
@@ -1465,6 +1484,8 @@ class call {
1465
1484
  channeldef.remote.icepwd = this.sdp.remote.sdp.media[ 0 ].icePwd
1466
1485
  }
1467
1486
 
1487
+ channeldef.preferredcall = preferredcall
1488
+
1468
1489
  /* We might have already opened our audio when we received 183 (early). */
1469
1490
  await this.#openchannelsforanswer( channeldef )
1470
1491
  }
@@ -1472,16 +1493,18 @@ class call {
1472
1493
 
1473
1494
  /**
1474
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.
1475
- * @param { object } options
1476
- * @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 ]
1477
1499
  *
1478
1500
  * @return {Promise} Returns a promise which resolves if the call is answered, otherwise rejects the promise.
1479
1501
  */
1480
- async answer( options = {} ) {
1502
+ async answer( options = { early: false, preferredcall: undefined } ) {
1481
1503
 
1482
1504
  if( this.canceled || this.established ) return
1483
1505
 
1484
- await this.#choosecodecforanswer()
1506
+ await this.#choosecodecforanswer( options.preferredcall )
1507
+
1485
1508
  if( this.canceled ) return
1486
1509
 
1487
1510
  if( options.early ) {
@@ -1553,12 +1576,12 @@ class call {
1553
1576
  */
1554
1577
 
1555
1578
  if( this._timers.anyevent ) clearTimeout( this._timers.anyevent )
1556
- this._timers.anyevent = false
1579
+ this._timers.anyevent = undefined
1557
1580
 
1558
1581
  const r = this._promises.resolve.channelevent
1559
- this._promises.resolve.channelevent = false
1560
- this._promises.reject.channelevent = false
1561
- this._promises.promise.channelevent = false
1582
+ this._promises.resolve.channelevent = undefined
1583
+ this._promises.reject.channelevent = undefined
1584
+ this._promises.promise.channelevent = undefined
1562
1585
  if( r ) r( e )
1563
1586
  }
1564
1587
 
@@ -1595,7 +1618,7 @@ class call {
1595
1618
 
1596
1619
  A telephone event will resolve this promise as we typically need speech to be interupted
1597
1620
  by the user. Note, peeking a telephone-event (i.e. DTMF) will not clear it like waitfortelevents will.
1598
- @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
1599
1622
  */
1600
1623
  waitforanyevent( constraints, timeout = 500 ) {
1601
1624
 
@@ -1611,9 +1634,9 @@ class call {
1611
1634
 
1612
1635
  this._timers.anyevent = setTimeout( () => {
1613
1636
  const r = this._promises.resolve.channelevent
1614
- this._promises.promise.channelevent = false
1615
- this._promises.resolve.channelevent = false
1616
- this._promises.reject.channelevent = false
1637
+ this._promises.promise.channelevent = undefined
1638
+ this._promises.resolve.channelevent = undefined
1639
+ this._promises.reject.channelevent = undefined
1617
1640
  if( r ) r( "timeout" )
1618
1641
  }, timeout * 1000 )
1619
1642
 
@@ -2193,8 +2216,8 @@ class call {
2193
2216
  @param { string } address - remote address (ip)
2194
2217
  @param { number } port - remote port
2195
2218
  @param { number } codec
2196
- @param { string } fingerprint - remote sha 256 fingerprint
2197
- @param { string } mode - "active"|"passive"
2219
+ @param { string } [ fingerprint ] - remote sha 256 fingerprint
2220
+ @param { string } [ mode ] - "active"|"passive"
2198
2221
  */
2199
2222
  static _createchannelremotedef( address, port, codec, fingerprint, mode /* active|passive */ ) {
2200
2223
  const chandef = {
@@ -2218,6 +2241,8 @@ class call {
2218
2241
 
2219
2242
  /**
2220
2243
  Sets our hangup cause correctly - if not already set.
2244
+ @param { string } src
2245
+ @param { object } [ reason ]
2221
2246
  @private
2222
2247
  */
2223
2248
  _sethangupcause( src, reason ) {
@@ -2248,24 +2273,24 @@ class call {
2248
2273
  /* Clean up promises (ensure they are resolved) and clear any timers */
2249
2274
  for ( const [ key, value ] of Object.entries( this._timers ) ) {
2250
2275
  if( value ) clearTimeout( value )
2251
- this._timers[ key ] = false
2276
+ this._timers[ key ] = undefined
2252
2277
  }
2253
2278
 
2254
2279
  const authreject = this._promises.reject.auth
2255
- this._promises.reject.auth = false
2256
- this._promises.resolve.auth = false
2257
- 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)" ) )
2258
2283
 
2259
2284
  const chanev = this._promises.reject.channelevent
2260
- this._promises.resolve.channelevent = false
2261
- this._promises.reject.channelevent = false
2262
- this._promises.promise.channelevent = false
2285
+ this._promises.resolve.channelevent = undefined
2286
+ this._promises.reject.channelevent = undefined
2287
+ this._promises.promise.channelevent = undefined
2263
2288
  if( chanev ) chanev( Error( "Call hungup" ) )
2264
2289
 
2265
2290
  const resolves = []
2266
2291
  for ( const [ key, value ] of Object.entries( this._promises.resolve ) ) {
2267
2292
  if( value ) resolves.push( value )
2268
- this._promises.resolve[ key ] = false
2293
+ this._promises.resolve[ key ] = undefined
2269
2294
  }
2270
2295
 
2271
2296
  /* Call outstanding resolves for promises - this will trigger out hangup promise also */
@@ -2284,8 +2309,8 @@ class call {
2284
2309
  * Used by our frame to a) continue a hangup which has been initiated by either us or the network.
2285
2310
  * Complete the hangup, including hanging up all children and waiting for them to complete their
2286
2311
  * hangup.
2287
- * @param {string} [us] - "us"|"wire"
2288
- * @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
2289
2314
  * @private
2290
2315
  */
2291
2316
  async _onhangup( src = "us", reason ) {
@@ -2375,16 +2400,16 @@ class call {
2375
2400
  }
2376
2401
 
2377
2402
  await this._promises.promise.hangup
2378
- this._promises.promise.hangup = false
2379
- this._promises.resolve.hangup = false
2403
+ this._promises.promise.hangup = undefined
2404
+ this._promises.resolve.hangup = undefined
2380
2405
 
2381
2406
  }
2382
2407
 
2383
2408
  /**
2384
- Send an UPDATE. Use to updated called id, caller id, sdp etc. Send in dialog - TODO look how to send
2385
- early as this is recomended in the RFC.
2386
- @param { Object } options
2387
- @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
2388
2413
  */
2389
2414
  async update( options ) {
2390
2415
 
@@ -2452,19 +2477,23 @@ class call {
2452
2477
  @summary Creates a new SIP dialog. Returns a promise which resolves
2453
2478
  when the dialog is either answered (or cancelled for some reason).
2454
2479
  The promise resolves to a new call is one is generated, or undefined if not.
2455
- @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.
2456
2481
  @param { string } [ options.contact ] - The contact string
2457
2482
  @param { boolean } [ options.orphan ] - If present and true then orphan the new call
2483
+ @param { object } [ options.auth ]
2458
2484
  @param { string } [ options.auth.username ] - If SIP auth required username
2459
2485
  @param { string } [ options.auth.password ] - If SIP auth required password
2460
2486
  @param { object } [ options.headers ] - Object containing extra sip headers required.
2461
2487
  @param { object } [ options.uactimeout ] - override the deault timeout
2462
2488
  @param { boolean } [ options.late ] - late negotiation
2463
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 ]
2464
2491
  @param { string } [ options.entity.username ]
2465
2492
  @param { string } [ options.entity.realm ]
2466
2493
  @param { string } [ options.entity.uri ]
2467
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
2468
2497
  @param { object } [ callbacks ]
2469
2498
  @param { earlycallback } [ callbacks.early ] - callback to provide a call object with early call (pre dialog)
2470
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
@@ -2486,10 +2515,13 @@ class call {
2486
2515
 
2487
2516
  options.headers[ "Max-Forwards" ] = maxforwards
2488
2517
 
2489
- if( !options.orphan ) {
2518
+ if( !options.orphan && !options.parent ) {
2490
2519
  options.parent = this
2520
+
2521
+ if ( !options.preferredcall )
2522
+ options.preferredcall = options.parent.channels.audio
2491
2523
  }
2492
-
2524
+
2493
2525
  return await call.newuac( options, callbacks )
2494
2526
  }
2495
2527
 
@@ -2598,13 +2630,17 @@ class call {
2598
2630
  * @param { object } [ channeldef ]
2599
2631
  */
2600
2632
  async #openrelatedchannel( channeldef ) {
2601
-
2602
2633
  const relatedcall = this.other
2603
- if( relatedcall && relatedcall.channels.audio )
2604
- this.channels.audio = await relatedcall.channels.audio.openchannel( channeldef, this._handlechannelevents.bind( this ) )
2605
- 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
2606
2643
  this.channels.audio = await projectrtp.openchannel( channeldef, this._handlechannelevents.bind( this ) )
2607
-
2608
2644
  }
2609
2645
 
2610
2646
  /**
@@ -2624,12 +2660,12 @@ class call {
2624
2660
  /**
2625
2661
  *
2626
2662
  */
2627
- async #openchannelsfornewuac() {
2663
+ async #openchannelsfornewuac( channeldef = undefined ) {
2628
2664
  if( this.options.late ) {
2629
2665
  this.options.noAck = true /* this is a MUST for late negotiation */
2630
2666
  } else {
2631
2667
 
2632
- await this.#openrelatedchannel()
2668
+ await this.#openrelatedchannel( channeldef )
2633
2669
 
2634
2670
  this.sdp.local = sdpgen.create().addcodecs( this.options.preferedcodecs )
2635
2671
  this.sdp.local.setaudioport( this.channels.audio.local.port )
@@ -2783,6 +2819,7 @@ class call {
2783
2819
  @param { object } [ options ] - Options object. See default_options in index.js for more details.
2784
2820
  @param { call } [ options.parent ] - the parent call object
2785
2821
  @param { string } [ options.contact ] - The contact string
2822
+ @param { object } [ options.auth ]
2786
2823
  @param { string } [ options.auth.username ] - If SIP auth required username
2787
2824
  @param { string } [ options.auth.password ] - If SIP auth required password
2788
2825
  @param { object } [ options.headers ] - Object containing extra sip headers required.
@@ -2791,6 +2828,7 @@ class call {
2791
2828
  @param { boolean } [ options.late ] - late negotiation
2792
2829
  @param { boolean } [ options.privacy ] - sets the privacy
2793
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 ]}
2794
2832
  @param { string } [ options.entity.username ]
2795
2833
  @param { string } [ options.entity.realm ]
2796
2834
  @param { string } [ options.entity.uri ]
@@ -2799,6 +2837,7 @@ class call {
2799
2837
  @param { object } [ options.callerid ]
2800
2838
  @param { string } [ options.callerid.number ]
2801
2839
  @param { string } [ options.callerid.name ]
2840
+ @param { object } [ options.preferredcall ] another related call which we may want to use the rtp host on
2802
2841
  @param { object } [ callbacks ]
2803
2842
  @param { earlycallback } [ callbacks.early ] - callback to provide a call object with early call (pre dialog)
2804
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
@@ -2847,7 +2886,7 @@ class call {
2847
2886
  newcall.options.headers = tmpheaders
2848
2887
 
2849
2888
  newcall.#confignetwork( options )
2850
- await newcall.#openchannelsfornewuac()
2889
+ await newcall.#openchannelsfornewuac( { "preferredcall" : options.preferredcall } )
2851
2890
 
2852
2891
  let newdialog
2853
2892
  try {
@@ -2924,7 +2963,7 @@ class call {
2924
2963
  */
2925
2964
  #setdialog( d ) {
2926
2965
  clearTimeout( this._timers.newuac )
2927
- this._timers.newuac = false
2966
+ this._timers.newuac = undefined
2928
2967
 
2929
2968
  if( this.destroyedcancelledorhungup ) return
2930
2969
 
@@ -2960,7 +2999,7 @@ class call {
2960
2999
  Create a new object when we receive an INVITE request.
2961
3000
 
2962
3001
  @param { object } req - req object from drachtio
2963
- @param { res } res - res object from drachtio
3002
+ @param { object } res - res object from drachtio
2964
3003
  @returns { Promise< call > }
2965
3004
  */
2966
3005
  static async frominvite( req, res ) {
@@ -2988,7 +3027,7 @@ class call {
2988
3027
  @private
2989
3028
  */
2990
3029
  c._req = req
2991
- c._req.on( "cancel", ( req ) => c._oncanceled( req ) )
3030
+ c._req.on( "cancel", ( /*req*/ ) => c._oncanceled( /*req*/ ) )
2992
3031
 
2993
3032
  /**
2994
3033
  @member
@@ -3022,13 +3061,11 @@ class call {
3022
3061
  */
3023
3062
  set uactimeout( ms ) {
3024
3063
  if( this.established ) return
3025
- const msi = parseInt( ms )
3026
- if( isNaN( msi ) ) return
3027
3064
 
3028
3065
  clearTimeout( this._timers.newuac )
3029
3066
  this._timers.newuac = setTimeout( () => {
3030
3067
  this.hangup( hangupcodes.REQUEST_TIMEOUT )
3031
- }, msi )
3068
+ }, ms )
3032
3069
  }
3033
3070
  }
3034
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.7",
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