@babblevoice/babble-drachtio-callmanager 2.3.8 → 2.3.10

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,41 @@ 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
207
+
208
+ /** @summary Other channels which we might need - for things like opening a channel on the same node. */
209
+ this.relatives = new Set()
189
210
 
190
211
  /**
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
- */
212
+ * @typedef {Object} epochs
213
+ * @property {number} startat UNIX timestamp of when the call was started (created)
214
+ * @property {number} answerat UNIX timestamp of when the call was answered
215
+ * @property {number} endat UNIX timestamp of when the call ended
216
+ */
196
217
 
197
218
  /** @member {epochs} */
198
219
  this.epochs = {
@@ -203,13 +224,15 @@ class call {
203
224
  }
204
225
 
205
226
  /**
206
- @typedef {Object} sipdialog
207
- @property {object} tags
208
- @property {string} tags.local
209
- @property {string} tags.remote
210
- */
211
- /** @member {sipdialog} */
227
+ * @typedef { object } sipdialog
228
+ * @property { string } callid
229
+ * @property { object } tags
230
+ * @property { string } tags.local
231
+ * @property { string } tags.remote
232
+ */
233
+ /** @member { sipdialog } */
212
234
  this.sip = {
235
+ "callid": undefined,
213
236
  "tags": {
214
237
  "remote": "",
215
238
  "local": ""
@@ -217,32 +240,23 @@ class call {
217
240
  }
218
241
 
219
242
  /**
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
243
+ * For inbound calls - this is discovered by authentication. For outbound
244
+ * this is requested by the caller - i.e. the destination is the registered user.
245
+ * @type { entity }
246
+ * Protected for this module.
231
247
  */
232
248
  this._entity
233
249
 
234
250
  /**
235
251
  Override caller id or name.
236
- @member { _remote }
237
252
  @private
238
253
  */
239
254
  this._remote = {
240
- "id": false,
241
- "name": false
255
+ "id": undefined,
256
+ "name": undefined
242
257
  }
243
258
 
244
259
  /**
245
- * @member { object }
246
260
  * @summary contains network information regarding call
247
261
  */
248
262
  this.network = {
@@ -254,8 +268,7 @@ class call {
254
268
  }
255
269
 
256
270
  /**
257
- @member {object}
258
- @summary user definable object that allows other modules to store data in this call.
271
+ * @summary user definable object that allows other modules to store data in this call.
259
272
  */
260
273
  this.vars = {}
261
274
 
@@ -266,24 +279,23 @@ class call {
266
279
  this._receivedtelevents = ""
267
280
 
268
281
  /**
269
- @member {object}
270
- @private
282
+ * @private
271
283
  */
272
284
  this._promises = {
273
285
  "resolve": {
274
- "auth": false,
275
- "hangup": false,
276
- "events": false,
277
- "channelevent": false
286
+ "auth": undefined,
287
+ "hangup": undefined,
288
+ "events": undefined,
289
+ "channelevent": undefined
278
290
  },
279
291
  "reject": {
280
- "auth": false,
281
- "channelevent": false
292
+ "auth": undefined,
293
+ "channelevent": undefined
282
294
  },
283
295
  "promise": {
284
- "hangup": false,
285
- "events": false,
286
- "channelevent": false
296
+ "hangup": undefined,
297
+ "events": undefined,
298
+ "channelevent": undefined
287
299
  }
288
300
  }
289
301
 
@@ -292,52 +304,61 @@ class call {
292
304
  } )
293
305
 
294
306
  /**
295
- @member {object}
296
- @private
307
+ * @private
297
308
  */
298
309
  this._timers = {
299
- "auth": false,
300
- "newuac": false,
301
- "events": false,
302
- "seinterval": false,
303
- "anyevent": false
310
+ "auth": undefined,
311
+ "newuac": undefined,
312
+ "events": undefined,
313
+ "seinterval": undefined,
314
+ "anyevent": undefined
304
315
  }
305
316
 
306
317
  /**
307
- @member {object}
308
- @private
318
+ * @private
309
319
  */
310
320
  this._em = new events.EventEmitter()
311
321
 
312
- /* copy default */
322
+ /**
323
+ * @typedef { Object } options
324
+ * @property { string } [ contact ] contact string
325
+ * @property { string } [ preferedcodecs ] as it says
326
+ * @property { boolean } [ rfc2833 ] if set to true enable 2833
327
+ * @property { string } [ display ] how the user should be displayed
328
+ * @property { Array } [ headers ]
329
+ * @property { number } [ uactimeout ] timeout in mS
330
+ * @property { boolean } [ late ] - do we use late negotiation
331
+ * @property { boolean } [ noAck ] do not use - converts our options into Drachtio options
332
+ * @property { string } [ localSdp ] do not use - what we pass into drachtio
333
+ */
334
+ /**
335
+ * copy default
336
+ * @type { options }
337
+ */
313
338
  this.options = { ...callmanager.options }
314
339
 
315
340
  /**
316
- @member
317
- @private
341
+ * @private
318
342
  */
319
343
  this._auth = sipauth.create( callmanager.options.proxy )
320
344
 
321
345
  this.referauthrequired = callmanager.options.referauthrequired
322
346
 
323
347
  /**
324
- Enable access for other modules.
348
+ * Enable access for other modules.
325
349
  */
326
350
  this.hangupcodes = hangupcodes
327
- }
328
351
 
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
- */
352
+ /**
353
+ * If the call is referred somewhere, this is the url we use
354
+ * @type { string }
355
+ */
356
+ this.referingtouri
357
+ }
337
358
 
338
359
  /**
339
- Returns the entity if known (i.e. outbound or inbound authed).
340
- @returns { Promise< entity > }
360
+ * Returns the entity if known (i.e. outbound or inbound authed).
361
+ * @returns { Promise< entity > }
341
362
  */
342
363
  get entity() {
343
364
 
@@ -381,7 +402,6 @@ class call {
381
402
  if( !e.uri && !( e.username && e.realm ) ) return
382
403
  this._entity = e
383
404
 
384
- this._entity.name = ""
385
405
  this._entity.display = ""
386
406
 
387
407
  if( this._entity.uri ) {
@@ -408,7 +428,7 @@ class call {
408
428
 
409
429
  /**
410
430
  * Sets caller id
411
- * @param { callerid } rem
431
+ * @param { string } callerid
412
432
  */
413
433
  set callerid( callerid ) {
414
434
  this._remote.id = callerid
@@ -416,7 +436,7 @@ class call {
416
436
 
417
437
  /**
418
438
  * Sets caller id name
419
- * @param { calleridname } rem
439
+ * @param { string } calleridname
420
440
  */
421
441
  set calleridname( calleridname ) {
422
442
  this._remote.name = calleridname
@@ -578,7 +598,7 @@ class call {
578
598
 
579
599
  /**
580
600
  hasmedia
581
- @return {bool} - true if the call has media (i.e. is established on not held).
601
+ @return { boolean } - true if the call has media (i.e. is established on not held).
582
602
  */
583
603
  get hasmedia() {
584
604
  if( this.state.held ) return false
@@ -597,7 +617,7 @@ class call {
597
617
 
598
618
  /**
599
619
  trying
600
- @return {bool} - true if the call has been trying.
620
+ @return { boolean } - true if the call has been trying.
601
621
  */
602
622
  get trying() {
603
623
  return this.state.trying
@@ -605,7 +625,7 @@ class call {
605
625
 
606
626
  /**
607
627
  ringing
608
- @return {bool} - true if the call has been ringing.
628
+ @return { boolean } - true if the call has been ringing.
609
629
  */
610
630
  get ringing() {
611
631
  return this.state.ringing
@@ -620,7 +640,7 @@ class call {
620
640
 
621
641
  /**
622
642
  established - if the call isn't already established then set the answerat time.
623
- @param {bool} s - true if the call has been established.
643
+ @param { boolean } s - true if the call has been established.
624
644
  */
625
645
  set established( s ) {
626
646
  if( this.state.established != s ) {
@@ -631,7 +651,7 @@ class call {
631
651
 
632
652
  /**
633
653
  established
634
- @return {bool} - true if the call has been established.
654
+ @return { boolean } - true if the call has been established.
635
655
  */
636
656
  get established() {
637
657
  return this.state.established
@@ -639,7 +659,7 @@ class call {
639
659
 
640
660
  /**
641
661
  @summary canceled - if the call isn't already canceled then set the endat time.
642
- @type {boolean}
662
+ @type { boolean }
643
663
  */
644
664
  set canceled( s ) {
645
665
  if( this.state.canceled != s ) {
@@ -658,7 +678,7 @@ class call {
658
678
 
659
679
  /**
660
680
  destroyed - if the call isn't already desroyed then set the endat time.
661
- @param {bool} s - true if the call has been destroyed.
681
+ @param { boolean } s - true if the call has been destroyed.
662
682
  */
663
683
  set destroyed( s ) {
664
684
  if( this.state.destroyed != s ) {
@@ -669,7 +689,7 @@ class call {
669
689
 
670
690
  /**
671
691
  destroyed
672
- @return {bool} - true if teh call has been destroyed.
692
+ @return { boolean } - true if teh call has been destroyed.
673
693
  */
674
694
  get destroyed() {
675
695
  return true == this.state.destroyed
@@ -681,7 +701,7 @@ class call {
681
701
 
682
702
  /**
683
703
  @summary the current state of the call as a string: trying|proceeding|early|confirmed|terminated
684
- @return {string}
704
+ @return { string }
685
705
  */
686
706
  get statestr() {
687
707
  if( this.state.established ) {
@@ -705,54 +725,50 @@ class call {
705
725
 
706
726
  /**
707
727
  duration
708
- @return {number} - the number of seconds between now (or endat if ended) and the time the call was started.
728
+ @return { number } - the number of seconds between now (or endat if ended) and the time the call was started.
709
729
  */
710
730
  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 )
731
+ if( 0 !== this.epochs.endat ) return this.epochs.endat - this.epochs.startat
732
+ return Math.floor( +new Date() / 1000 ) - this.epochs.startat
713
733
  }
714
734
 
715
735
  /**
716
736
  Get the estrablished time.
717
- @return {number} - the number of seconds between now (or endat if ended) and the time the call was answered.
737
+ @return { number } - the number of seconds between now (or endat if ended) and the time the call was answered.
718
738
  */
719
739
  get billingduration() {
720
740
  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 )
741
+ if( 0 !== this.epochs.endat ) return this.epochs.endat - this.epochs.answerat
742
+ return Math.floor( +new Date() / 1000 ) - this.epochs.answerat
723
743
  }
724
744
 
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
745
 
731
746
  /**
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
- */
747
+ * Callback for events we pass back to inerested parties.
748
+ * Registers an event callback for this specific call. An event sink registered
749
+ * on this member will receive events only for this call. We emit on call specific
750
+ * emitter and a global emitter.
751
+ * @param { string } ev - The contact string for registered or other sip contact
752
+ * @param { (...args: any[] ) => void } cb
753
+ */
738
754
  on( ev, cb ) {
739
755
  this._em.on( ev, cb )
740
756
  }
741
757
 
742
758
  /**
743
- See event emitter once
744
- @param { string } ev - The contact string for registered or other sip contact
745
- @param { call.event } cb
746
- */
759
+ * See event emitter once
760
+ * @param { string } ev - The contact string for registered or other sip contact
761
+ * @param { (...args: any[] ) => void } cb
762
+ */
747
763
  once( ev, cb ) {
748
764
  this._em.once( ev, cb )
749
765
  }
750
766
 
751
767
  /**
752
- See event emitter off
753
- @param { string } ev - The contact string for registered or other sip contact
754
- @param { call.event } cb
755
- */
768
+ * See event emitter off
769
+ * @param { string } ev - The contact string for registered or other sip contact
770
+ * @param { (...args: any[] ) => void } cb
771
+ */
756
772
  off( ev, cb ) {
757
773
  if( !cb ) {
758
774
  this._em.removeAllListeners( ev )
@@ -763,9 +779,9 @@ class call {
763
779
  }
764
780
 
765
781
  /**
766
- See event emitter removeAllListeners
767
- @param { string } ev - The contact string for registered or other sip contact
768
- */
782
+ * See event emitter removeAllListeners
783
+ * @param { string } [ ev ] - The contact string for registered or other sip contact
784
+ */
769
785
  removealllisteners( ev ) {
770
786
  if( !ev ) {
771
787
  const evnames = this._em.eventNames()
@@ -876,16 +892,19 @@ class call {
876
892
  /**
877
893
  Emits the event call.pick to allow other parts of dial plan to give up on further processing.
878
894
  It wuld be normal to bridge this call to another after this call has been made.
895
+ @return { call }
879
896
  */
880
897
  pick() {
881
898
  this.state.picked = true
882
899
  this._em.emit( "call.pick", this )
900
+ return this
883
901
  }
884
902
 
885
903
  /**
886
904
  Delink calls logically - any calls which have parent or children they are all removed.
887
905
  when the dialog is either answered (or doesn't answer for some reason).
888
906
  The promise resolves to a new call is one is generated, or undefined if not.
907
+ @return { call }
889
908
  */
890
909
  detach() {
891
910
  if( this.parent ) {
@@ -896,13 +915,16 @@ class call {
896
915
  child.parent = false
897
916
  }
898
917
 
899
- this.parent = false
918
+ this.parent = undefined
900
919
  this.children.clear()
920
+ return this
901
921
  }
902
922
 
903
923
  /**
904
- Logically adopt a child call
905
- @param { call } other
924
+ * Logically adopt a child call
925
+ * @param { object } other
926
+ * @param { boolean } [ mix ]
927
+ * @return { call }
906
928
  */
907
929
  adopt( other, mix ) {
908
930
  other.parent = this
@@ -922,6 +944,29 @@ class call {
922
944
  this.epochs.mix = Math.floor( +new Date() / 1000 )
923
945
  other.epochs.mix = Math.floor( +new Date() / 1000 )
924
946
  }
947
+ return this
948
+ }
949
+
950
+ /**
951
+ * Create a bond between us and another call. This is currently only used
952
+ * to provide other channels we know we might need to open a channel on
953
+ * the same node as. (replaces preferredcall)
954
+ * @param { object } relative
955
+ * @return { call }
956
+ */
957
+ bond( relative ) {
958
+ if( !relative ) return
959
+ this.relatives.add( relative )
960
+ return this
961
+ }
962
+
963
+ /**
964
+ * Disown distant relatives.
965
+ * @return { call }
966
+ */
967
+ disown() {
968
+ this.relatives.clear()
969
+ return this
925
970
  }
926
971
 
927
972
  /**
@@ -931,7 +976,7 @@ class call {
931
976
  _onring() {
932
977
  if( this.state.ringing ) return
933
978
  this.state.ringing = true
934
- if( false !== this.parent ) {
979
+ if( undefined !== this.parent ) {
935
980
  this.parent.ring()
936
981
  }
937
982
 
@@ -1134,18 +1179,20 @@ class call {
1134
1179
 
1135
1180
  /**
1136
1181
  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
1182
+ @return { object | boolean } returns call object or if none false
1138
1183
  */
1139
1184
  get other() {
1140
1185
  if( this.parent ) return this.parent
1141
1186
 
1187
+ /* first established */
1142
1188
  for( const child of this.children ) {
1143
1189
  if( child.established ) {
1144
1190
  return child
1145
1191
  }
1146
1192
  }
1147
1193
 
1148
- if( 0 < this.children.length ) return this.children.values().next().value
1194
+ /* or the first */
1195
+ if( 0 < this.children.size ) return this.children.values().next().value
1149
1196
 
1150
1197
  return false
1151
1198
  }
@@ -1172,10 +1219,10 @@ class call {
1172
1219
  }
1173
1220
 
1174
1221
  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
1222
+ this._promises.reject.auth( new SipError( hangupcodes.REQUEST_TIMEOUT, "Auth timed out" ) )
1223
+ this._promises.resolve.auth = undefined
1224
+ this._promises.reject.auth = undefined
1225
+ this._timers.auth = undefined
1179
1226
 
1180
1227
  this.hangup( hangupcodes.REQUEST_TIMEOUT )
1181
1228
 
@@ -1206,7 +1253,7 @@ class call {
1206
1253
  this._req = req
1207
1254
  this._res = res
1208
1255
 
1209
- req.on( "cancel", ( req ) => this._oncanceled( req ) )
1256
+ req.on( "cancel", ( /*req*/ ) => this._oncanceled( /*req*/ ) )
1210
1257
 
1211
1258
  if( !this._auth.has( this._req ) ) return false
1212
1259
 
@@ -1230,14 +1277,14 @@ class call {
1230
1277
 
1231
1278
  await this.hangup( hangupcodes.FORBIDDEN )
1232
1279
 
1233
- const r = this._promises.reject.auth
1234
- this._promises.resolve.auth = false
1235
- this._promises.reject.auth = false
1280
+ const reject = this._promises.reject.auth
1281
+ this._promises.resolve.auth = undefined
1282
+ this._promises.reject.auth = undefined
1236
1283
 
1237
1284
  clearTimeout( this._timers.auth )
1238
- this._timers.auth = false
1285
+ this._timers.auth = undefined
1239
1286
 
1240
- if( r ) r()
1287
+ if( reject ) reject( new SipError( hangupcodes.FORBIDDEN, "Bad Auth" ))
1241
1288
 
1242
1289
  return false
1243
1290
  }
@@ -1255,11 +1302,11 @@ class call {
1255
1302
  this.state.authed = true
1256
1303
  await callstore.set( this )
1257
1304
 
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()
1305
+ const resolve = this._promises.resolve.auth
1306
+ this._promises.resolve.auth = undefined
1307
+ this._promises.reject.auth = undefined
1308
+ this._timers.auth = undefined
1309
+ if( resolve ) resolve()
1263
1310
 
1264
1311
  this._em.emit( "call.authed", this )
1265
1312
  callmanager.options.em.emit( "call.authed", this )
@@ -1298,14 +1345,14 @@ class call {
1298
1345
  if( this._promises.resolve.events ) {
1299
1346
  const r = this._promises.resolve.events
1300
1347
 
1301
- this._promises.resolve.events = false
1302
- this._promises.promise.events = false
1348
+ this._promises.resolve.events = undefined
1349
+ this._promises.promise.events = undefined
1303
1350
  r( ourmatch[ 0 ] )
1304
1351
  }
1305
1352
 
1306
1353
  if( this._timers.events ) {
1307
1354
  clearTimeout( this._timers.events )
1308
- this._timers.events = false
1355
+ this._timers.events = undefined
1309
1356
  }
1310
1357
  }
1311
1358
  }
@@ -1313,9 +1360,9 @@ class call {
1313
1360
 
1314
1361
  /**
1315
1362
  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..
1363
+ @param { string | RegExp } [match] - reg exp matching what is required from the user.
1364
+ @param { number } [timeout] - time to wait before giving up.
1365
+ @return { Promise } - the promise either resolves to a string if it matches or undefined if it times out..
1319
1366
  */
1320
1367
  waitfortelevents( match = /[0-9A-D*#]/, timeout = 30000 ) {
1321
1368
 
@@ -1330,9 +1377,9 @@ class call {
1330
1377
  this._promises.resolve.events()
1331
1378
  }
1332
1379
 
1333
- this._promises.resolve.events = false
1334
- this._promises.promise.events = false
1335
- this._timers.events = false
1380
+ this._promises.resolve.events = undefined
1381
+ this._promises.promise.events = undefined
1382
+ this._timers.events = undefined
1336
1383
  delete this.eventmatch
1337
1384
 
1338
1385
  }, timeout )
@@ -1417,7 +1464,7 @@ class call {
1417
1464
  /* we have already opened a channel (probably early now answering) */
1418
1465
  this.channels.audio.remote( channeldef.remote )
1419
1466
  } else {
1420
-
1467
+
1421
1468
  await this.#openrelatedchannel( channeldef )
1422
1469
 
1423
1470
  this.sdp.local = sdpgen.create()
@@ -1437,7 +1484,8 @@ class call {
1437
1484
  }
1438
1485
 
1439
1486
  /**
1440
- *
1487
+ * that can be used to open the new channel's node.
1488
+ *
1441
1489
  * @returns { Promise }
1442
1490
  */
1443
1491
  async #choosecodecforanswer() {
@@ -1474,16 +1522,17 @@ class call {
1474
1522
 
1475
1523
  /**
1476
1524
  * 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).
1525
+ * @param { object } [ options ]
1526
+ * @param { boolean } [ options.early ] - don't answer the channel (establish) but establish early media (respond to 183).
1479
1527
  *
1480
1528
  * @return {Promise} Returns a promise which resolves if the call is answered, otherwise rejects the promise.
1481
1529
  */
1482
- async answer( options = {} ) {
1530
+ async answer( options = { early: false } ) {
1483
1531
 
1484
1532
  if( this.canceled || this.established ) return
1485
1533
 
1486
1534
  await this.#choosecodecforanswer()
1535
+
1487
1536
  if( this.canceled ) return
1488
1537
 
1489
1538
  if( options.early ) {
@@ -1555,12 +1604,12 @@ class call {
1555
1604
  */
1556
1605
 
1557
1606
  if( this._timers.anyevent ) clearTimeout( this._timers.anyevent )
1558
- this._timers.anyevent = false
1607
+ this._timers.anyevent = undefined
1559
1608
 
1560
1609
  const r = this._promises.resolve.channelevent
1561
- this._promises.resolve.channelevent = false
1562
- this._promises.reject.channelevent = false
1563
- this._promises.promise.channelevent = false
1610
+ this._promises.resolve.channelevent = undefined
1611
+ this._promises.reject.channelevent = undefined
1612
+ this._promises.promise.channelevent = undefined
1564
1613
  if( r ) r( e )
1565
1614
  }
1566
1615
 
@@ -1597,7 +1646,7 @@ class call {
1597
1646
 
1598
1647
  A telephone event will resolve this promise as we typically need speech to be interupted
1599
1648
  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
1649
+ @param { object } constraints - event to filter for from our RTP server - excluding DTMF events - these will always return
1601
1650
  */
1602
1651
  waitforanyevent( constraints, timeout = 500 ) {
1603
1652
 
@@ -1613,9 +1662,9 @@ class call {
1613
1662
 
1614
1663
  this._timers.anyevent = setTimeout( () => {
1615
1664
  const r = this._promises.resolve.channelevent
1616
- this._promises.promise.channelevent = false
1617
- this._promises.resolve.channelevent = false
1618
- this._promises.reject.channelevent = false
1665
+ this._promises.promise.channelevent = undefined
1666
+ this._promises.resolve.channelevent = undefined
1667
+ this._promises.reject.channelevent = undefined
1619
1668
  if( r ) r( "timeout" )
1620
1669
  }, timeout * 1000 )
1621
1670
 
@@ -2195,8 +2244,8 @@ class call {
2195
2244
  @param { string } address - remote address (ip)
2196
2245
  @param { number } port - remote port
2197
2246
  @param { number } codec
2198
- @param { string } fingerprint - remote sha 256 fingerprint
2199
- @param { string } mode - "active"|"passive"
2247
+ @param { string } [ fingerprint ] - remote sha 256 fingerprint
2248
+ @param { string } [ mode ] - "active"|"passive"
2200
2249
  */
2201
2250
  static _createchannelremotedef( address, port, codec, fingerprint, mode /* active|passive */ ) {
2202
2251
  const chandef = {
@@ -2220,6 +2269,8 @@ class call {
2220
2269
 
2221
2270
  /**
2222
2271
  Sets our hangup cause correctly - if not already set.
2272
+ @param { string } src
2273
+ @param { object } [ reason ]
2223
2274
  @private
2224
2275
  */
2225
2276
  _sethangupcause( src, reason ) {
@@ -2250,24 +2301,24 @@ class call {
2250
2301
  /* Clean up promises (ensure they are resolved) and clear any timers */
2251
2302
  for ( const [ key, value ] of Object.entries( this._timers ) ) {
2252
2303
  if( value ) clearTimeout( value )
2253
- this._timers[ key ] = false
2304
+ this._timers[ key ] = undefined
2254
2305
  }
2255
2306
 
2256
2307
  const authreject = this._promises.reject.auth
2257
- this._promises.reject.auth = false
2258
- this._promises.resolve.auth = false
2259
- if( authreject ) authreject( this )
2308
+ this._promises.reject.auth = undefined
2309
+ this._promises.resolve.auth = undefined
2310
+ if( authreject ) authreject( new SipError( hangupcodes.REQUEST_TIMEOUT, "Auth timed out (cleanup)" ) )
2260
2311
 
2261
2312
  const chanev = this._promises.reject.channelevent
2262
- this._promises.resolve.channelevent = false
2263
- this._promises.reject.channelevent = false
2264
- this._promises.promise.channelevent = false
2313
+ this._promises.resolve.channelevent = undefined
2314
+ this._promises.reject.channelevent = undefined
2315
+ this._promises.promise.channelevent = undefined
2265
2316
  if( chanev ) chanev( Error( "Call hungup" ) )
2266
2317
 
2267
2318
  const resolves = []
2268
2319
  for ( const [ key, value ] of Object.entries( this._promises.resolve ) ) {
2269
2320
  if( value ) resolves.push( value )
2270
- this._promises.resolve[ key ] = false
2321
+ this._promises.resolve[ key ] = undefined
2271
2322
  }
2272
2323
 
2273
2324
  /* Call outstanding resolves for promises - this will trigger out hangup promise also */
@@ -2286,8 +2337,8 @@ class call {
2286
2337
  * Used by our frame to a) continue a hangup which has been initiated by either us or the network.
2287
2338
  * Complete the hangup, including hanging up all children and waiting for them to complete their
2288
2339
  * 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
2340
+ * @param { string } [ src ] - "us"|"wire"
2341
+ * @param { object } [ reason ] - one of the reasons from the hangupcodes enum - only used if we havn't alread set our reason
2291
2342
  * @private
2292
2343
  */
2293
2344
  async _onhangup( src = "us", reason ) {
@@ -2377,16 +2428,16 @@ class call {
2377
2428
  }
2378
2429
 
2379
2430
  await this._promises.promise.hangup
2380
- this._promises.promise.hangup = false
2381
- this._promises.resolve.hangup = false
2431
+ this._promises.promise.hangup = undefined
2432
+ this._promises.resolve.hangup = undefined
2382
2433
 
2383
2434
  }
2384
2435
 
2385
2436
  /**
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
2437
+ * Send an UPDATE. Use to updated called id, caller id, sdp etc. Send in dialog - TODO look how to send
2438
+ * early as this is recomended in the RFC.
2439
+ * @param { object } options
2440
+ * @param { entity } options.remote
2390
2441
  */
2391
2442
  async update( options ) {
2392
2443
 
@@ -2454,19 +2505,22 @@ class call {
2454
2505
  @summary Creates a new SIP dialog. Returns a promise which resolves
2455
2506
  when the dialog is either answered (or cancelled for some reason).
2456
2507
  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.
2508
+ @param { object } [ options ] - Options object. See default_options in index.js for more details.
2458
2509
  @param { string } [ options.contact ] - The contact string
2459
2510
  @param { boolean } [ options.orphan ] - If present and true then orphan the new call
2511
+ @param { object } [ options.auth ]
2460
2512
  @param { string } [ options.auth.username ] - If SIP auth required username
2461
2513
  @param { string } [ options.auth.password ] - If SIP auth required password
2462
2514
  @param { object } [ options.headers ] - Object containing extra sip headers required.
2463
2515
  @param { object } [ options.uactimeout ] - override the deault timeout
2464
2516
  @param { boolean } [ options.late ] - late negotiation
2465
2517
  @param { entity } [ options.entity ] - used to store this call against and look up a contact string if not supplied.
2518
+ @param { object } [ options.entity ]
2466
2519
  @param { string } [ options.entity.username ]
2467
2520
  @param { string } [ options.entity.realm ]
2468
2521
  @param { string } [ options.entity.uri ]
2469
2522
  @param { number } [ options.entity.max ] - if included no more than this number of calls for this entity (only if we look user up)
2523
+ @param { object } [ options.parent ] - the call we wish to become parent
2470
2524
  @param { object } [ callbacks ]
2471
2525
  @param { earlycallback } [ callbacks.early ] - callback to provide a call object with early call (pre dialog)
2472
2526
  @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 +2542,10 @@ class call {
2488
2542
 
2489
2543
  options.headers[ "Max-Forwards" ] = maxforwards
2490
2544
 
2491
- if( !options.orphan ) {
2545
+ if( !options.orphan && !options.parent ) {
2492
2546
  options.parent = this
2493
2547
  }
2494
-
2548
+
2495
2549
  return await call.newuac( options, callbacks )
2496
2550
  }
2497
2551
 
@@ -2600,13 +2654,24 @@ class call {
2600
2654
  * @param { object } [ channeldef ]
2601
2655
  */
2602
2656
  async #openrelatedchannel( channeldef ) {
2603
-
2604
2657
  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
2608
- this.channels.audio = await projectrtp.openchannel( channeldef, this._handlechannelevents.bind( this ) )
2658
+ /* TODO: this is a hack. projectrtp has become too complicated with both a listen and connect
2659
+ mechanism. This is causing problems in code like this. There is no interface to
2660
+ detect which mode the channel is in - but the channels property will exist on a connect
2661
+ style channel. projectrtp will get a rewrite to support only one. */
2662
+ if( relatedcall && relatedcall.channels.audio && relatedcall.channels.audio.channels ) {
2663
+ this.channels.audio = await this.other.channels.audio.openchannel( channeldef, this._handlechannelevents.bind( this ) )
2664
+ return
2665
+ }
2609
2666
 
2667
+ for( const other of this.relatives ) {
2668
+ if( other.channels && other.channels.audio ) {
2669
+ this.channels.audio = await other.channels.audio.openchannel( channeldef, this._handlechannelevents.bind( this ) )
2670
+ return
2671
+ }
2672
+ }
2673
+
2674
+ this.channels.audio = await projectrtp.openchannel( channeldef, this._handlechannelevents.bind( this ) )
2610
2675
  }
2611
2676
 
2612
2677
  /**
@@ -2626,12 +2691,12 @@ class call {
2626
2691
  /**
2627
2692
  *
2628
2693
  */
2629
- async #openchannelsfornewuac() {
2694
+ async #openchannelsfornewuac( channeldef = undefined ) {
2630
2695
  if( this.options.late ) {
2631
2696
  this.options.noAck = true /* this is a MUST for late negotiation */
2632
2697
  } else {
2633
2698
 
2634
- await this.#openrelatedchannel()
2699
+ await this.#openrelatedchannel( channeldef )
2635
2700
 
2636
2701
  this.sdp.local = sdpgen.create().addcodecs( this.options.preferedcodecs )
2637
2702
  this.sdp.local.setaudioport( this.channels.audio.local.port )
@@ -2785,6 +2850,7 @@ class call {
2785
2850
  @param { object } [ options ] - Options object. See default_options in index.js for more details.
2786
2851
  @param { call } [ options.parent ] - the parent call object
2787
2852
  @param { string } [ options.contact ] - The contact string
2853
+ @param { object } [ options.auth ]
2788
2854
  @param { string } [ options.auth.username ] - If SIP auth required username
2789
2855
  @param { string } [ options.auth.password ] - If SIP auth required password
2790
2856
  @param { object } [ options.headers ] - Object containing extra sip headers required.
@@ -2793,6 +2859,7 @@ class call {
2793
2859
  @param { boolean } [ options.late ] - late negotiation
2794
2860
  @param { boolean } [ options.privacy ] - sets the privacy
2795
2861
  @param { entity } [ options.entity ] - used to store this call against and look up a contact string if not supplied.
2862
+ @param { object } [ options.entity ]}
2796
2863
  @param { string } [ options.entity.username ]
2797
2864
  @param { string } [ options.entity.realm ]
2798
2865
  @param { string } [ options.entity.uri ]
@@ -2801,6 +2868,7 @@ class call {
2801
2868
  @param { object } [ options.callerid ]
2802
2869
  @param { string } [ options.callerid.number ]
2803
2870
  @param { string } [ options.callerid.name ]
2871
+ @param { call } [ options.bond ] - other channel to bond to for pottential channel pairing
2804
2872
  @param { object } [ callbacks ]
2805
2873
  @param { earlycallback } [ callbacks.early ] - callback to provide a call object with early call (pre dialog)
2806
2874
  @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
@@ -2823,6 +2891,8 @@ class call {
2823
2891
  options.parent.adopt( newcall )
2824
2892
  }
2825
2893
 
2894
+ newcall.bond( options.bond )
2895
+
2826
2896
  newcall.options = {
2827
2897
  headers: { ...options.headers }
2828
2898
  }
@@ -2926,7 +2996,7 @@ class call {
2926
2996
  */
2927
2997
  #setdialog( d ) {
2928
2998
  clearTimeout( this._timers.newuac )
2929
- this._timers.newuac = false
2999
+ this._timers.newuac = undefined
2930
3000
 
2931
3001
  if( this.destroyedcancelledorhungup ) return
2932
3002
 
@@ -2962,7 +3032,7 @@ class call {
2962
3032
  Create a new object when we receive an INVITE request.
2963
3033
 
2964
3034
  @param { object } req - req object from drachtio
2965
- @param { res } res - res object from drachtio
3035
+ @param { object } res - res object from drachtio
2966
3036
  @returns { Promise< call > }
2967
3037
  */
2968
3038
  static async frominvite( req, res ) {
@@ -2990,7 +3060,7 @@ class call {
2990
3060
  @private
2991
3061
  */
2992
3062
  c._req = req
2993
- c._req.on( "cancel", ( req ) => c._oncanceled( req ) )
3063
+ c._req.on( "cancel", ( /*req*/ ) => c._oncanceled( /*req*/ ) )
2994
3064
 
2995
3065
  /**
2996
3066
  @member
@@ -3024,13 +3094,11 @@ class call {
3024
3094
  */
3025
3095
  set uactimeout( ms ) {
3026
3096
  if( this.established ) return
3027
- const msi = parseInt( ms )
3028
- if( isNaN( msi ) ) return
3029
3097
 
3030
3098
  clearTimeout( this._timers.newuac )
3031
3099
  this._timers.newuac = setTimeout( () => {
3032
3100
  this.hangup( hangupcodes.REQUEST_TIMEOUT )
3033
- }, msi )
3101
+ }, ms )
3034
3102
  }
3035
3103
  }
3036
3104
 
@@ -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.10",
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