@babblevoice/babble-drachtio-callmanager 3.6.9 → 3.6.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/lib/call.js +308 -139
- package/lib/callmanager.js +17 -9
- package/package.json +1 -1
package/lib/call.js
CHANGED
|
@@ -52,6 +52,21 @@ function keynameslower( obj ) {
|
|
|
52
52
|
}, {} )
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
/**
|
|
56
|
+
* @summary Finds the correct key in a case-insensitive manner and retrieves the key and value.
|
|
57
|
+
* @param {Object} headers - The headers object.
|
|
58
|
+
* @param {string} targetKey - The key to search for.
|
|
59
|
+
* @return {Object|undefined} - Returns an object with the correct key and value, or undefined if not found.
|
|
60
|
+
*/
|
|
61
|
+
function getheadervalue( headers, targetKey ) {
|
|
62
|
+
const lowerCaseTargetKey = targetKey.toLowerCase()
|
|
63
|
+
for(const key in headers) {
|
|
64
|
+
if( key.toLowerCase() === lowerCaseTargetKey) {
|
|
65
|
+
return { key, value: headers[key] }
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
55
70
|
/*
|
|
56
71
|
Enum for different reasons for hangup.
|
|
57
72
|
*/
|
|
@@ -173,6 +188,7 @@ class call {
|
|
|
173
188
|
"trying": false,
|
|
174
189
|
"early": false,
|
|
175
190
|
"ringing": false,
|
|
191
|
+
"establishing": false, /** we have received 200 but we send ack - late neg only */
|
|
176
192
|
"established": false,
|
|
177
193
|
"canceled": false,
|
|
178
194
|
"destroyed": false,
|
|
@@ -364,6 +380,8 @@ class call {
|
|
|
364
380
|
* @type { string }
|
|
365
381
|
*/
|
|
366
382
|
this.referingtouri
|
|
383
|
+
|
|
384
|
+
this.errors = []
|
|
367
385
|
}
|
|
368
386
|
|
|
369
387
|
/**
|
|
@@ -1207,26 +1225,30 @@ class call {
|
|
|
1207
1225
|
*/
|
|
1208
1226
|
async _onearly() {
|
|
1209
1227
|
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1228
|
+
try {
|
|
1229
|
+
if( this.state.established ) return
|
|
1230
|
+
if( !this._res || !this._res.msg || !this._res.msg.body ) return
|
|
1231
|
+
|
|
1232
|
+
/* we have this._res */
|
|
1233
|
+
this.sdp.remote = sdpgen.create( this._res.msg.body )
|
|
1234
|
+
this.#parsesrtpsetup()
|
|
1235
|
+
await this.answer( { "early": true } )
|
|
1236
|
+
|
|
1237
|
+
if( !this.parent || this.parent.state.established ) return
|
|
1238
|
+
|
|
1239
|
+
await this.parent.answer( { "early": true } )
|
|
1240
|
+
await this.channels.audio.mix( this.parent.channels.audio )
|
|
1241
|
+
|
|
1242
|
+
this.parent._res.send( 183, {
|
|
1243
|
+
headers: {
|
|
1244
|
+
"User-Agent": "project",
|
|
1245
|
+
"Supported": "replaces"
|
|
1246
|
+
},
|
|
1247
|
+
"body": this.parent.sdp.local.toString()
|
|
1248
|
+
} )
|
|
1249
|
+
} catch( e ) {
|
|
1250
|
+
throw new Error( e )
|
|
1251
|
+
}
|
|
1230
1252
|
}
|
|
1231
1253
|
|
|
1232
1254
|
async #answerparent() {
|
|
@@ -1329,7 +1351,7 @@ class call {
|
|
|
1329
1351
|
await this.#openrelatedchannel( channeldef )
|
|
1330
1352
|
|
|
1331
1353
|
if ( !this.channels.audio ) {
|
|
1332
|
-
this
|
|
1354
|
+
this.#servererror( "Failed to open channel" )
|
|
1333
1355
|
return
|
|
1334
1356
|
}
|
|
1335
1357
|
|
|
@@ -1351,7 +1373,8 @@ class call {
|
|
|
1351
1373
|
.rtcpmux()
|
|
1352
1374
|
}
|
|
1353
1375
|
|
|
1354
|
-
this
|
|
1376
|
+
this._dialog = await this._dialog.ack( this.sdp.local.toString() )
|
|
1377
|
+
this.established = true
|
|
1355
1378
|
this._addevents( this._dialog )
|
|
1356
1379
|
|
|
1357
1380
|
await this.#answerparent()
|
|
@@ -1666,7 +1689,7 @@ class call {
|
|
|
1666
1689
|
|
|
1667
1690
|
await this.#openrelatedchannel( channeldef )
|
|
1668
1691
|
if( !this.channels.audio ) {
|
|
1669
|
-
this
|
|
1692
|
+
this.#servererror( "Failed to open channel" )
|
|
1670
1693
|
return
|
|
1671
1694
|
}
|
|
1672
1695
|
|
|
@@ -1720,6 +1743,10 @@ class call {
|
|
|
1720
1743
|
if( this.canceled || this.established ) return
|
|
1721
1744
|
|
|
1722
1745
|
await this.#choosecodecforanswer()
|
|
1746
|
+
if( !this.channels.audio ) {
|
|
1747
|
+
this.#servererror( "Failed to open channel" )
|
|
1748
|
+
return
|
|
1749
|
+
}
|
|
1723
1750
|
|
|
1724
1751
|
if( this.canceled ) return
|
|
1725
1752
|
|
|
@@ -1730,7 +1757,7 @@ class call {
|
|
|
1730
1757
|
} else {
|
|
1731
1758
|
|
|
1732
1759
|
if ( !this.sdp.local ) {
|
|
1733
|
-
this
|
|
1760
|
+
this.#servererror( "No local SDP" )
|
|
1734
1761
|
return
|
|
1735
1762
|
}
|
|
1736
1763
|
|
|
@@ -2155,25 +2182,10 @@ class call {
|
|
|
2155
2182
|
@private
|
|
2156
2183
|
*/
|
|
2157
2184
|
async mix( othercall ) {
|
|
2158
|
-
if
|
|
2159
|
-
|
|
2160
|
-
!= this.channels.audio.connection.instance ) {
|
|
2161
|
-
|
|
2162
|
-
const channeldef = await othercall.#createchannelremotedef()
|
|
2163
|
-
|
|
2164
|
-
const oldchannel = othercall.channels.audio
|
|
2165
|
-
const newchannel = await this.#openchannel( channeldef, othercall )
|
|
2166
|
-
if( !newchannel ) {
|
|
2167
|
-
this.hangup( hangupcodes.SERVER_ERROR )
|
|
2168
|
-
return
|
|
2169
|
-
}
|
|
2170
|
-
|
|
2171
|
-
await othercall.bond( this ).reinvite( channeldef, newchannel )
|
|
2172
|
-
|
|
2173
|
-
await oldchannel.unmix()
|
|
2174
|
-
oldchannel.close()
|
|
2175
|
-
}
|
|
2185
|
+
if( !othercall.channels.audio ) return
|
|
2186
|
+
if( !this.channels.audio ) return
|
|
2176
2187
|
|
|
2188
|
+
await this.#mixdifferentnode( othercall )
|
|
2177
2189
|
await this.channels.audio.mix( othercall.channels.audio )
|
|
2178
2190
|
|
|
2179
2191
|
this._em.emit( "call.mix", this )
|
|
@@ -2185,6 +2197,51 @@ class call {
|
|
|
2185
2197
|
othercall.epochs.mix = Math.floor( +new Date() / 1000 )
|
|
2186
2198
|
}
|
|
2187
2199
|
|
|
2200
|
+
/**
|
|
2201
|
+
* hangs up and throws exception to get out
|
|
2202
|
+
* @param { string } reason
|
|
2203
|
+
*/
|
|
2204
|
+
#servererror( reason ) {
|
|
2205
|
+
this.hangup( hangupcodes.SERVER_ERROR )
|
|
2206
|
+
this.errors.push( { now: +new Date(), reason } )
|
|
2207
|
+
|
|
2208
|
+
const ourerror = Error( reason )
|
|
2209
|
+
// @ts-ignore
|
|
2210
|
+
ourerror.normalandsilent = true
|
|
2211
|
+
throw ourerror
|
|
2212
|
+
}
|
|
2213
|
+
|
|
2214
|
+
/**
|
|
2215
|
+
*
|
|
2216
|
+
* @param { call } othercall
|
|
2217
|
+
* @returns { Promise }
|
|
2218
|
+
*/
|
|
2219
|
+
async #mixdifferentnode( othercall ) {
|
|
2220
|
+
|
|
2221
|
+
if( !othercall.channels.audio.connection ) return
|
|
2222
|
+
if( !othercall.channels.audio.connection.instance ) return
|
|
2223
|
+
|
|
2224
|
+
if( !this.channels.audio.connection ) return
|
|
2225
|
+
if( !this.channels.audio.connection.instance ) return
|
|
2226
|
+
|
|
2227
|
+
if( othercall.channels.audio.connection.instance == this.channels.audio.connection.instance ) return
|
|
2228
|
+
|
|
2229
|
+
const channeldef = await othercall.#createchannelremotedef()
|
|
2230
|
+
|
|
2231
|
+
const oldchannel = othercall.channels.audio
|
|
2232
|
+
const newchannel = await this.#openchannel( channeldef, othercall )
|
|
2233
|
+
if( !newchannel ) {
|
|
2234
|
+
this.#servererror( "Failed to open channel" )
|
|
2235
|
+
return
|
|
2236
|
+
}
|
|
2237
|
+
|
|
2238
|
+
await othercall.bond( this ).reinvite( channeldef, newchannel )
|
|
2239
|
+
|
|
2240
|
+
await oldchannel.unmix()
|
|
2241
|
+
oldchannel.close()
|
|
2242
|
+
|
|
2243
|
+
}
|
|
2244
|
+
|
|
2188
2245
|
/**
|
|
2189
2246
|
Mix two calls. If the two calls are on a different node
|
|
2190
2247
|
the second call is bonded and reinvited.
|
|
@@ -2193,22 +2250,29 @@ class call {
|
|
|
2193
2250
|
*/
|
|
2194
2251
|
async #openchannel( channeldef, bindcall ) {
|
|
2195
2252
|
|
|
2196
|
-
|
|
2253
|
+
try {
|
|
2254
|
+
let chan
|
|
2255
|
+
let bind
|
|
2256
|
+
if( bindcall ) bind = bindcall
|
|
2257
|
+
else bind = this
|
|
2258
|
+
|
|
2259
|
+
if ( this.channels.audio ) {
|
|
2260
|
+
chan = await this.channels.audio.openchannel(
|
|
2261
|
+
channeldef, bind._handlechannelevents.bind( bind ) )
|
|
2262
|
+
} else {
|
|
2263
|
+
chan = await projectrtp.openchannel(
|
|
2264
|
+
channeldef, bind._handlechannelevents.bind( bind ) )
|
|
2265
|
+
}
|
|
2197
2266
|
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
}
|
|
2202
|
-
|
|
2203
|
-
|
|
2267
|
+
bind.channels.count++
|
|
2268
|
+
|
|
2269
|
+
return chan
|
|
2270
|
+
} catch( e ) {
|
|
2271
|
+
if( this.channels.audio )
|
|
2272
|
+
console.trace( "problem opening channel on related channel", e )
|
|
2273
|
+
else
|
|
2274
|
+
console.trace( "problem opening channel on prtp", e )
|
|
2204
2275
|
}
|
|
2205
|
-
|
|
2206
|
-
if ( bindcall )
|
|
2207
|
-
bindcall.channels.count++
|
|
2208
|
-
else
|
|
2209
|
-
this.channels.count++
|
|
2210
|
-
|
|
2211
|
-
return chan
|
|
2212
2276
|
}
|
|
2213
2277
|
|
|
2214
2278
|
/**
|
|
@@ -2527,7 +2591,7 @@ class call {
|
|
|
2527
2591
|
b_1.channels.audio.unmix()
|
|
2528
2592
|
await b_1.waitforanyevent( { "action": "mix", "event": "finished" }, 0.5 )
|
|
2529
2593
|
}
|
|
2530
|
-
b_1.hangup(
|
|
2594
|
+
b_1.hangup( hangupcodes.ATTENDED_TRANSFER )
|
|
2531
2595
|
}
|
|
2532
2596
|
|
|
2533
2597
|
/**
|
|
@@ -2758,7 +2822,14 @@ class call {
|
|
|
2758
2822
|
async #createchannelremotedef() {
|
|
2759
2823
|
|
|
2760
2824
|
const iswebrtc = this._iswebrtc
|
|
2761
|
-
|
|
2825
|
+
|
|
2826
|
+
let target
|
|
2827
|
+
try{
|
|
2828
|
+
target = await this.#getremotetarget( iswebrtc )
|
|
2829
|
+
} catch( e ) {
|
|
2830
|
+
throw new Error( e )
|
|
2831
|
+
}
|
|
2832
|
+
|
|
2762
2833
|
|
|
2763
2834
|
if( !target ) return
|
|
2764
2835
|
const address = target.address
|
|
@@ -2856,7 +2927,7 @@ class call {
|
|
|
2856
2927
|
callmanager.options.em.emit( "call.reporting", this )
|
|
2857
2928
|
|
|
2858
2929
|
return 0
|
|
2859
|
-
} ).catch( () => {} )
|
|
2930
|
+
} ).catch( ( e ) => { console.error( e ) } )
|
|
2860
2931
|
}
|
|
2861
2932
|
|
|
2862
2933
|
/**
|
|
@@ -2883,7 +2954,6 @@ class call {
|
|
|
2883
2954
|
*/
|
|
2884
2955
|
// eslint-disable-next-line complexity
|
|
2885
2956
|
async _onhangup( src = "us", reason ) {
|
|
2886
|
-
|
|
2887
2957
|
if( this._state._onhangup ) {
|
|
2888
2958
|
await this.waitforhangup()
|
|
2889
2959
|
return
|
|
@@ -2891,32 +2961,7 @@ class call {
|
|
|
2891
2961
|
this._state._onhangup = true
|
|
2892
2962
|
|
|
2893
2963
|
this._sethangupcause( src, reason )
|
|
2894
|
-
|
|
2895
|
-
if( "wire" == src ) {
|
|
2896
|
-
/*
|
|
2897
|
-
1. Hangup our children regardless of our state
|
|
2898
|
-
2. If we are established and the only child child - hangup our parent (unless otherwise told not to: parent.continueonotherhangup)
|
|
2899
|
-
*/
|
|
2900
|
-
const hangups = []
|
|
2901
|
-
if( this.options.hangupchildrenonhangup ) {
|
|
2902
|
-
for( const child of this.children ) {
|
|
2903
|
-
if( !child.options.continueonotherhangup ) {
|
|
2904
|
-
hangups.push( child.hangup( this.hangup_cause ) )
|
|
2905
|
-
}
|
|
2906
|
-
}
|
|
2907
|
-
}
|
|
2908
|
-
|
|
2909
|
-
if( this.established && this.options.hangupparentonhangup && this.parent ) {
|
|
2910
|
-
if( !this.parent.options.continueonotherhangup && 2 > this.parent.children.size ) {
|
|
2911
|
-
hangups.push( this.parent.hangup( this.hangup_cause ) )
|
|
2912
|
-
}
|
|
2913
|
-
}
|
|
2914
|
-
|
|
2915
|
-
/* wait for all relatives to complete their hangup */
|
|
2916
|
-
if( 0 < hangups.length ) {
|
|
2917
|
-
await Promise.all( hangups )
|
|
2918
|
-
}
|
|
2919
|
-
}
|
|
2964
|
+
await this.#handlewirehangup( src )
|
|
2920
2965
|
|
|
2921
2966
|
/* flag destroyed so when we receive our close event we know what to do */
|
|
2922
2967
|
this.destroyed = true
|
|
@@ -2928,11 +2973,69 @@ class call {
|
|
|
2928
2973
|
an event on the event listener so we can safely return here and not call _cleanup */
|
|
2929
2974
|
if( "object" == typeof cl ) return
|
|
2930
2975
|
} catch( e ) {
|
|
2931
|
-
console.error( "timed out waiting for channel close" )
|
|
2976
|
+
console.error( "timed out waiting for channel close", e )
|
|
2932
2977
|
}
|
|
2933
2978
|
}
|
|
2934
2979
|
|
|
2935
|
-
|
|
2980
|
+
try {
|
|
2981
|
+
this._cleanup()
|
|
2982
|
+
} catch( e ) {
|
|
2983
|
+
throw new Error( e )
|
|
2984
|
+
}
|
|
2985
|
+
}
|
|
2986
|
+
|
|
2987
|
+
/**
|
|
2988
|
+
*
|
|
2989
|
+
* @param { "us"|"wire" } src
|
|
2990
|
+
* @returns
|
|
2991
|
+
*/
|
|
2992
|
+
async #handlewirehangup( src ) {
|
|
2993
|
+
|
|
2994
|
+
if( "wire" != src ) return
|
|
2995
|
+
|
|
2996
|
+
/*
|
|
2997
|
+
1. Hangup our children regardless of our state
|
|
2998
|
+
2. If we are established and the only child child - hangup our parent (unless otherwise told not to: parent.continueonotherhangup)
|
|
2999
|
+
*/
|
|
3000
|
+
const hangups = this.#hangupchildren()
|
|
3001
|
+
this.#hangupparent( hangups )
|
|
3002
|
+
|
|
3003
|
+
/* wait for all relatives to complete their hangup */
|
|
3004
|
+
if( 0 < hangups.length ) {
|
|
3005
|
+
try{
|
|
3006
|
+
await Promise.all( hangups )
|
|
3007
|
+
} catch( e ) {
|
|
3008
|
+
throw new Error( e )
|
|
3009
|
+
}
|
|
3010
|
+
}
|
|
3011
|
+
}
|
|
3012
|
+
|
|
3013
|
+
/**
|
|
3014
|
+
* If options allow hangup parent
|
|
3015
|
+
* @param { Array } hangups
|
|
3016
|
+
*/
|
|
3017
|
+
#hangupparent( hangups ) {
|
|
3018
|
+
if( this.established && this.options.hangupparentonhangup && this.parent ) {
|
|
3019
|
+
if( !this.parent.options.continueonotherhangup && 2 > this.parent.children.size ) {
|
|
3020
|
+
hangups.push( this.parent.hangup( this.hangup_cause ) )
|
|
3021
|
+
}
|
|
3022
|
+
}
|
|
3023
|
+
}
|
|
3024
|
+
|
|
3025
|
+
/**
|
|
3026
|
+
* If options allow - hangup other children
|
|
3027
|
+
* @returns { Array< Promise > }
|
|
3028
|
+
*/
|
|
3029
|
+
#hangupchildren() {
|
|
3030
|
+
const hangups = []
|
|
3031
|
+
if( this.options.hangupchildrenonhangup ) {
|
|
3032
|
+
for( const child of this.children ) {
|
|
3033
|
+
if( !child.options.continueonotherhangup ) {
|
|
3034
|
+
hangups.push( child.hangup( this.hangup_cause ) )
|
|
3035
|
+
}
|
|
3036
|
+
}
|
|
3037
|
+
}
|
|
3038
|
+
return hangups
|
|
2936
3039
|
}
|
|
2937
3040
|
|
|
2938
3041
|
/**
|
|
@@ -2943,29 +3046,61 @@ class call {
|
|
|
2943
3046
|
*
|
|
2944
3047
|
*/
|
|
2945
3048
|
async hangup( reason, tone = false, source = "us" ) {
|
|
3049
|
+
try {
|
|
3050
|
+
if( this._state._hangup || this._state._onhangup ) {
|
|
3051
|
+
await this.waitforhangup()
|
|
3052
|
+
return
|
|
3053
|
+
}
|
|
2946
3054
|
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
3055
|
+
this._sethangupcause( source, reason )
|
|
3056
|
+
this._state._hangup = true
|
|
3057
|
+
if( this.state.established ) {
|
|
3058
|
+
if( this.#hangupestablish( reason, tone ) ) return
|
|
3059
|
+
} else if( "uac" === this.type && this.state.trying ) {
|
|
3060
|
+
this.#hangupnotestablish()
|
|
3061
|
+
await this._onhangup( source, reason )
|
|
3062
|
+
return
|
|
3063
|
+
} else if( this._res ) {
|
|
3064
|
+
this._res.send( this.hangup_cause.sip )
|
|
3065
|
+
await this._onhangup( source, reason )
|
|
3066
|
+
return
|
|
3067
|
+
}
|
|
3068
|
+
|
|
3069
|
+
await this.#destroydialog()
|
|
3070
|
+
} catch( e ) {
|
|
3071
|
+
console.trace( e )
|
|
2950
3072
|
}
|
|
2951
3073
|
|
|
2952
|
-
this.
|
|
3074
|
+
await this._onhangup( source, reason )
|
|
3075
|
+
}
|
|
2953
3076
|
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
3077
|
+
/**
|
|
3078
|
+
*
|
|
3079
|
+
* @returns { Promise }
|
|
3080
|
+
*/
|
|
3081
|
+
async #destroydialog() {
|
|
3082
|
+
if( !this._dialog ) return
|
|
3083
|
+
if( !this._dialog.destroy ) return
|
|
2961
3084
|
|
|
2962
|
-
this.
|
|
3085
|
+
await this._dialog.destroy()
|
|
3086
|
+
}
|
|
2963
3087
|
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
3088
|
+
/**
|
|
3089
|
+
* We have played a tone - give it a limit.
|
|
3090
|
+
*/
|
|
3091
|
+
#scheduledelayedhangup() {
|
|
2967
3092
|
|
|
2968
|
-
|
|
3093
|
+
this._timers.delayedhangup = setTimeout( async () => {
|
|
3094
|
+
if( this._state._onhangup ) return
|
|
3095
|
+
try {
|
|
3096
|
+
await this.#destroydialog()
|
|
3097
|
+
} catch ( e ) {
|
|
3098
|
+
console.trace( e )
|
|
3099
|
+
}
|
|
3100
|
+
|
|
3101
|
+
await this._onhangup()
|
|
3102
|
+
|
|
3103
|
+
}, 5000 )
|
|
2969
3104
|
}
|
|
2970
3105
|
|
|
2971
3106
|
/**
|
|
@@ -2973,19 +3108,30 @@ class call {
|
|
|
2973
3108
|
* @param { boolean } tone
|
|
2974
3109
|
*/
|
|
2975
3110
|
#hangupestablish( reason, tone ) {
|
|
2976
|
-
if(
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
3111
|
+
if( !reason ) return false
|
|
3112
|
+
if( !tone ) return false
|
|
3113
|
+
if( "object" != typeof reason ) return false
|
|
3114
|
+
|
|
3115
|
+
switch( reason.sip ) {
|
|
3116
|
+
case 486:
|
|
3117
|
+
this._state._hangup = false
|
|
3118
|
+
this.play( this.engagedsoup )
|
|
3119
|
+
this.#scheduledelayedhangup()
|
|
3120
|
+
return true
|
|
3121
|
+
case 480:
|
|
3122
|
+
this._state._hangup = false
|
|
3123
|
+
this.play( this.unobtainablesoup )
|
|
3124
|
+
this.#scheduledelayedhangup()
|
|
3125
|
+
return true
|
|
2985
3126
|
}
|
|
3127
|
+
|
|
2986
3128
|
return false
|
|
3129
|
+
|
|
2987
3130
|
}
|
|
2988
3131
|
|
|
3132
|
+
/**
|
|
3133
|
+
* The call is not established so send a cancel.
|
|
3134
|
+
*/
|
|
2989
3135
|
#hangupnotestablish() {
|
|
2990
3136
|
try {
|
|
2991
3137
|
this.canceled = true
|
|
@@ -3071,19 +3217,21 @@ class call {
|
|
|
3071
3217
|
*/
|
|
3072
3218
|
async newuac( options, callbacks = {} ) {
|
|
3073
3219
|
|
|
3074
|
-
/* If max-forwards is not specified then we decrement the parent and pass on */
|
|
3075
3220
|
if( !( "headers" in options ) ) options.headers = {}
|
|
3221
|
+
/* If max-forwards is not specified then we decrement the parent and pass on */
|
|
3222
|
+
|
|
3223
|
+
const ouroptionsmaxforwards = getheadervalue( options.headers, "max-forwards" )
|
|
3224
|
+
const ourimportsmaxforwards = getheadervalue( this.propagate.headers, "max-forwards" )
|
|
3076
3225
|
|
|
3077
|
-
|
|
3078
|
-
|
|
3226
|
+
if( !ouroptionsmaxforwards && !ourimportsmaxforwards ) {
|
|
3227
|
+
let maxforwards = 70
|
|
3079
3228
|
if( this._req.has( "Max-Forwards" ) ) {
|
|
3080
3229
|
maxforwards = parseInt( this._req.get( "Max-Forwards" ) ) - 1
|
|
3081
3230
|
if( isNaN( maxforwards ) || 0 >= maxforwards ) return false
|
|
3082
3231
|
}
|
|
3232
|
+
options.headers[ "max-forwards" ] = maxforwards
|
|
3083
3233
|
}
|
|
3084
3234
|
|
|
3085
|
-
options.headers[ "max-forwards" ] = maxforwards
|
|
3086
|
-
|
|
3087
3235
|
if( !options.orphan && !options.parent ) {
|
|
3088
3236
|
options.parent = this
|
|
3089
3237
|
}
|
|
@@ -3201,26 +3349,30 @@ class call {
|
|
|
3201
3349
|
*/
|
|
3202
3350
|
async #openrelatedchannel( channeldef ) {
|
|
3203
3351
|
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
const othercall = this.other
|
|
3207
|
-
/* TODO: this is a hack. projectrtp has become too complicated with both a listen and connect
|
|
3208
|
-
mechanism. This is causing problems in code like this. There is no interface to
|
|
3209
|
-
detect which mode the channel is in - but the channels property will exist on a connect
|
|
3210
|
-
style channel. projectrtp will getrelatives a rewrite to support only one. */
|
|
3211
|
-
if( othercall && othercall.channels.audio ) {
|
|
3212
|
-
this.channels.audio = await othercall.#openchannel( channeldef, this )
|
|
3213
|
-
return
|
|
3214
|
-
}
|
|
3352
|
+
try {
|
|
3353
|
+
if( this.channels.audio ) return
|
|
3215
3354
|
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3355
|
+
const othercall = this.other
|
|
3356
|
+
/* TODO: this is a hack. projectrtp has become too complicated with both a listen and connect
|
|
3357
|
+
mechanism. This is causing problems in code like this. There is no interface to
|
|
3358
|
+
detect which mode the channel is in - but the channels property will exist on a connect
|
|
3359
|
+
style channel. projectrtp will getrelatives a rewrite to support only one. */
|
|
3360
|
+
if( othercall && othercall.channels.audio ) {
|
|
3361
|
+
this.channels.audio = await othercall.#openchannel( channeldef, this )
|
|
3219
3362
|
return
|
|
3220
3363
|
}
|
|
3364
|
+
|
|
3365
|
+
for( const other of this.relatives ) {
|
|
3366
|
+
if( other.channels && other.channels.audio ) {
|
|
3367
|
+
this.channels.audio = await other.#openchannel( channeldef, this )
|
|
3368
|
+
return
|
|
3369
|
+
}
|
|
3370
|
+
}
|
|
3371
|
+
|
|
3372
|
+
this.channels.audio = await this.#openchannel( channeldef )
|
|
3373
|
+
} catch( e ) {
|
|
3374
|
+
console.trace( e )
|
|
3221
3375
|
}
|
|
3222
|
-
|
|
3223
|
-
this.channels.audio = await this.#openchannel( channeldef )
|
|
3224
3376
|
}
|
|
3225
3377
|
|
|
3226
3378
|
/**
|
|
@@ -3247,7 +3399,7 @@ class call {
|
|
|
3247
3399
|
|
|
3248
3400
|
await this.#openrelatedchannel( channeldef )
|
|
3249
3401
|
if( !this.channels.audio ) {
|
|
3250
|
-
this
|
|
3402
|
+
this.#servererror( "Failed to open channel" )
|
|
3251
3403
|
return
|
|
3252
3404
|
}
|
|
3253
3405
|
|
|
@@ -3308,10 +3460,17 @@ class call {
|
|
|
3308
3460
|
console.trace( e )
|
|
3309
3461
|
}
|
|
3310
3462
|
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3463
|
+
try {
|
|
3464
|
+
if( true === this.#noack ) {
|
|
3465
|
+
await this._onlatebridge()
|
|
3466
|
+
} else {
|
|
3467
|
+
await this._onearlybridge()
|
|
3468
|
+
}
|
|
3469
|
+
} catch ( e ) {
|
|
3470
|
+
console.trace( e )
|
|
3471
|
+
if( this.destroyedcancelledorhungup ) {
|
|
3472
|
+
return
|
|
3473
|
+
}
|
|
3315
3474
|
}
|
|
3316
3475
|
|
|
3317
3476
|
try {
|
|
@@ -3635,6 +3794,11 @@ class call {
|
|
|
3635
3794
|
newcall.#setdialog( newdialog )
|
|
3636
3795
|
await newcall.#onnewuacsuccess( callbacks )
|
|
3637
3796
|
|
|
3797
|
+
if( newcall.destroyedcancelledorhungup ) {
|
|
3798
|
+
callstore.delete( newcall )
|
|
3799
|
+
if( callbacks.fail ) callbacks.fail( newcall )
|
|
3800
|
+
}
|
|
3801
|
+
|
|
3638
3802
|
return newcall
|
|
3639
3803
|
}
|
|
3640
3804
|
|
|
@@ -3649,6 +3813,11 @@ class call {
|
|
|
3649
3813
|
if( this.destroyedcancelledorhungup ) return
|
|
3650
3814
|
|
|
3651
3815
|
this._dialog = d
|
|
3816
|
+
|
|
3817
|
+
/* not established until we ack */
|
|
3818
|
+
this.state.establishing = true
|
|
3819
|
+
if( this.#noack ) return
|
|
3820
|
+
|
|
3652
3821
|
this.established = true
|
|
3653
3822
|
}
|
|
3654
3823
|
|
package/lib/callmanager.js
CHANGED
|
@@ -35,6 +35,7 @@ class callmanager {
|
|
|
35
35
|
Parse invite maessages from drachtio.
|
|
36
36
|
@private
|
|
37
37
|
*/
|
|
38
|
+
// eslint-disable-next-line complexity
|
|
38
39
|
async _oninvite( req, res, next ) {
|
|
39
40
|
if( "INVITE" !== req.msg.method ) return next()
|
|
40
41
|
|
|
@@ -59,15 +60,22 @@ class callmanager {
|
|
|
59
60
|
try {
|
|
60
61
|
await this.onnewcall( c )
|
|
61
62
|
} catch( e ) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
63
|
+
try{
|
|
64
|
+
/* auth failed or timed out excluded as this is noral(ish) */
|
|
65
|
+
if( "object" === typeof e ) {
|
|
66
|
+
if( 403 === e.code ) return
|
|
67
|
+
if( 408 === e.code ) return
|
|
68
|
+
if( true === e.normalandsilent ) return
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
console.trace( e )
|
|
72
|
+
|
|
73
|
+
if( c.destroyedcancelledorhungup ) return
|
|
74
|
+
|
|
75
|
+
c.hangup( this.hangupcodes.SERVER_ERROR )
|
|
76
|
+
} catch( e ) {
|
|
77
|
+
console.error( e )
|
|
78
|
+
}
|
|
71
79
|
}
|
|
72
80
|
}
|
|
73
81
|
}
|