@shenyin/embedded-call-widget 2.6.12 → 3.0.0
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/README.md +6 -2
- package/checksums.txt +5 -5
- package/embedded-call-widget-runtime.iife.js +275 -77
- package/embedded-call-widget-runtime.js +1697 -1430
- package/embedded-call-widget.iife.js +51 -13
- package/embedded-call-widget.js +91 -55
- package/manifest.json +18 -17
- package/package.json +1 -1
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
var EmbeddedCallWidgetRuntimeBundle=(function(Fe){"use strict";const
|
|
1
|
+
var EmbeddedCallWidgetRuntimeBundle=(function(Fe){"use strict";const Pt="0.21.1";class he extends Error{constructor(e){super(e),Object.setPrototypeOf(this,new.target.prototype)}}class Ne extends he{constructor(e){super(e||"Unsupported content type.")}}class ve extends he{constructor(e){super(e||"Request pending.")}}class kt extends he{constructor(e){super(e||"Unspecified session description handler error.")}}class Ue extends he{constructor(){super("The session has terminated.")}}class Se extends he{constructor(e){super(e||"An error occurred during state transition.")}}class Ht{constructor(e){this.incomingAckRequest=e}get request(){return this.incomingAckRequest.message}}class Mt{constructor(e){this.incomingByeRequest=e}get request(){return this.incomingByeRequest.message}accept(e){return this.incomingByeRequest.accept(e),Promise.resolve()}reject(e){return this.incomingByeRequest.reject(e),Promise.resolve()}}class qt{constructor(e){this.incomingCancelRequest=e}get request(){return this.incomingCancelRequest}}class Te{constructor(){this.listeners=new Array}addListener(e,t){const i=s=>{this.removeListener(i),e(s)};t?.once===!0?this.listeners.push(i):this.listeners.push(e)}emit(e){this.listeners.slice().forEach(t=>t(e))}removeAllListeners(){this.listeners=[]}removeListener(e){this.listeners=this.listeners.filter(t=>t!==e)}on(e){return this.addListener(e)}off(e){return this.removeListener(e)}once(e){return this.addListener(e,{once:!0})}}class Ot{constructor(e){this.incomingInfoRequest=e}get request(){return this.incomingInfoRequest.message}accept(e){return this.incomingInfoRequest.accept(e),Promise.resolve()}reject(e){return this.incomingInfoRequest.reject(e),Promise.resolve()}}class it{constructor(e){this.parameters={};for(const t in e)e.hasOwnProperty(t)&&this.setParam(t,e[t])}setParam(e,t){e&&(this.parameters[e.toLowerCase()]=typeof t>"u"||t===null?null:t.toString())}getParam(e){if(e)return this.parameters[e.toLowerCase()]}hasParam(e){return!!(e&&this.parameters[e.toLowerCase()]!==void 0)}deleteParam(e){if(e=e.toLowerCase(),this.hasParam(e)){const t=this.parameters[e];return delete this.parameters[e],t}}clearParams(){this.parameters={}}}class N extends it{constructor(e,t,i){super(i),this.uri=e,this._displayName=t}get friendlyName(){return this.displayName||this.uri.aor}get displayName(){return this._displayName}set displayName(e){this._displayName=e}clone(){return new N(this.uri.clone(),this._displayName,JSON.parse(JSON.stringify(this.parameters)))}toString(){let e=this.displayName||this.displayName==="0"?'"'+this.displayName+'" ':"";e+="<"+this.uri.toString()+">";for(const t in this.parameters)this.parameters.hasOwnProperty(t)&&(e+=";"+t,this.parameters[t]!==null&&(e+="="+this.parameters[t]));return e}}class z extends it{constructor(e="sip",t,i,s,r,n){if(super(r||{}),this.headers={},!i)throw new TypeError('missing or invalid "host" parameter');for(const o in n)n.hasOwnProperty(o)&&this.setHeader(o,n[o]);this.raw={scheme:e,user:t,host:i,port:s},this.normal={scheme:e.toLowerCase(),user:t,host:i.toLowerCase(),port:s}}get scheme(){return this.normal.scheme}set scheme(e){this.raw.scheme=e,this.normal.scheme=e.toLowerCase()}get user(){return this.normal.user}set user(e){this.normal.user=this.raw.user=e}get host(){return this.normal.host}set host(e){this.raw.host=e,this.normal.host=e.toLowerCase()}get aor(){return this.normal.user+"@"+this.normal.host}get port(){return this.normal.port}set port(e){this.normal.port=this.raw.port=e}setHeader(e,t){this.headers[this.headerize(e)]=t instanceof Array?t:[t]}getHeader(e){if(e)return this.headers[this.headerize(e)]}hasHeader(e){return!!e&&!!this.headers.hasOwnProperty(this.headerize(e))}deleteHeader(e){if(e=this.headerize(e),this.headers.hasOwnProperty(e)){const t=this.headers[e];return delete this.headers[e],t}}clearHeaders(){this.headers={}}clone(){return new z(this._raw.scheme,this._raw.user||"",this._raw.host,this._raw.port,JSON.parse(JSON.stringify(this.parameters)),JSON.parse(JSON.stringify(this.headers)))}toRaw(){return this._toString(this._raw)}toString(){return this._toString(this._normal)}get _normal(){return this.normal}get _raw(){return this.raw}_toString(e){let t=e.scheme+":";e.scheme.toLowerCase().match("^sips?$")||(t+="//"),e.user&&(t+=this.escapeUser(e.user)+"@"),t+=e.host,(e.port||e.port===0)&&(t+=":"+e.port);for(const s in this.parameters)this.parameters.hasOwnProperty(s)&&(t+=";"+s,this.parameters[s]!==null&&(t+="="+this.parameters[s]));const i=[];for(const s in this.headers)if(this.headers.hasOwnProperty(s))for(const r in this.headers[s])this.headers[s].hasOwnProperty(r)&&i.push(s+"="+this.headers[s][r]);return i.length>0&&(t+="?"+i.join("&")),t}escapeUser(e){let t;try{t=decodeURIComponent(e)}catch(i){throw i}return encodeURIComponent(t).replace(/%3A/ig,":").replace(/%2B/ig,"+").replace(/%3F/ig,"?").replace(/%2F/ig,"/")}headerize(e){const t={"Call-Id":"Call-ID",Cseq:"CSeq","Min-Se":"Min-SE",Rack:"RAck",Rseq:"RSeq","Www-Authenticate":"WWW-Authenticate"},i=e.toLowerCase().replace(/_/g,"-").split("-"),s=i.length;let r="";for(let n=0;n<s;n++)n!==0&&(r+="-"),r+=i[n].charAt(0).toUpperCase()+i[n].substring(1);return t[r]&&(r=t[r]),r}}function st(a,e){if(a.scheme!==e.scheme||a.user!==e.user||a.host!==e.host||a.port!==e.port)return!1;function t(r,n){const o=Object.keys(r.parameters),d=Object.keys(n.parameters);return!(!o.filter(h=>d.includes(h)).every(h=>r.parameters[h]===n.parameters[h])||!["user","ttl","method","transport"].every(h=>r.hasParam(h)&&n.hasParam(h)||!r.hasParam(h)&&!n.hasParam(h))||!["maddr"].every(h=>r.hasParam(h)&&n.hasParam(h)||!r.hasParam(h)&&!n.hasParam(h)))}if(!t(a,e))return!1;const i=Object.keys(a.headers),s=Object.keys(e.headers);if(i.length!==0||s.length!==0){if(i.length!==s.length)return!1;const r=i.filter(n=>s.includes(n));if(r.length!==s.length||!r.every(n=>a.headers[n].length&&e.headers[n].length&&a.headers[n][0]===e.headers[n][0]))return!1}return!0}function Le(a,e,t){return t=t||" ",a.length>e?a:(e-=a.length,t+=t.repeat(e),a+t.slice(0,e))}class pe extends Error{constructor(e,t,i,s){super(),this.message=e,this.expected=t,this.found=i,this.location=s,this.name="SyntaxError",typeof Object.setPrototypeOf=="function"?Object.setPrototypeOf(this,pe.prototype):this.__proto__=pe.prototype,typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,pe)}static buildMessage(e,t){function i(u){return u.charCodeAt(0).toString(16).toUpperCase()}function s(u){return u.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,h=>"\\x0"+i(h)).replace(/[\x10-\x1F\x7F-\x9F]/g,h=>"\\x"+i(h))}function r(u){return u.replace(/\\/g,"\\\\").replace(/\]/g,"\\]").replace(/\^/g,"\\^").replace(/-/g,"\\-").replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,h=>"\\x0"+i(h)).replace(/[\x10-\x1F\x7F-\x9F]/g,h=>"\\x"+i(h))}function n(u){switch(u.type){case"literal":return'"'+s(u.text)+'"';case"class":const h=u.parts.map(m=>Array.isArray(m)?r(m[0])+"-"+r(m[1]):r(m));return"["+(u.inverted?"^":"")+h+"]";case"any":return"any character";case"end":return"end of input";case"other":return u.description}}function o(u){const h=u.map(n);let m,S;if(h.sort(),h.length>0){for(m=1,S=1;m<h.length;m++)h[m-1]!==h[m]&&(h[S]=h[m],S++);h.length=S}switch(h.length){case 1:return h[0];case 2:return h[0]+" or "+h[1];default:return h.slice(0,-1).join(", ")+", or "+h[h.length-1]}}function d(u){return u?'"'+s(u)+'"':"end of input"}return"Expected "+o(e)+" but "+d(t)+" found."}format(e){let t="Error: "+this.message;if(this.location){let i=null,s;for(s=0;s<e.length;s++)if(e[s].source===this.location.source){i=e[s].text.split(/\r\n|\n|\r/g);break}let r=this.location.start,n=this.location.source+":"+r.line+":"+r.column;if(i){let o=this.location.end,d=Le("",r.line.toString().length," "),u=i[r.line-1],h=r.line===o.line?o.column:u.length+1;t+=`
|
|
2
2
|
--> `+n+`
|
|
3
3
|
`+d+` |
|
|
4
|
-
`+r.line+" | "+
|
|
4
|
+
`+r.line+" | "+u+`
|
|
5
5
|
`+d+" | "+Le("",r.column-1," ")+Le("",h-r.column,"^")}else t+=`
|
|
6
|
-
at `+n}return t}}function
|
|
6
|
+
at `+n}return t}}function Ft(a,e){e=e!==void 0?e:{};const t={},i=e.grammarSource,s={Contact:119,Name_Addr_Header:156,Record_Route:176,Request_Response:81,SIP_URI:45,Subscription_State:186,Supported:191,Require:182,Via:194,absoluteURI:84,Call_ID:118,Content_Disposition:130,Content_Length:135,Content_Type:136,CSeq:146,displayName:122,Event:149,From:151,host:52,Max_Forwards:154,Min_SE:213,Proxy_Authenticate:157,quoted_string:40,Refer_To:178,Replaces:179,Session_Expires:210,stun_URI:217,To:192,turn_URI:223,uuid:226,WWW_Authenticate:209,challenge:158,sipfrag:230,Referred_By:231};let r=119;const n=[`\r
|
|
7
7
|
`,p(`\r
|
|
8
|
-
`,!1),/^[0-9]/,$([["0","9"]],!1,!1),/^[a-zA-Z]/,$([["a","z"],["A","Z"]],!1,!1),/^[0-9a-fA-F]/,$([["0","9"],["a","f"],["A","F"]],!1,!1),/^[\0-\xFF]/,$([["\0","ÿ"]],!1,!1),/^["]/,$(['"'],!1,!1)," ",p(" ",!1)," ",p(" ",!1),/^[a-zA-Z0-9]/,$([["a","z"],["A","Z"],["0","9"]],!1,!1),";",p(";",!1),"/",p("/",!1),"?",p("?",!1),":",p(":",!1),"@",p("@",!1),"&",p("&",!1),"=",p("=",!1),"+",p("+",!1),"$",p("$",!1),",",p(",",!1),"-",p("-",!1),"_",p("_",!1),".",p(".",!1),"!",p("!",!1),"~",p("~",!1),"*",p("*",!1),"'",p("'",!1),"(",p("(",!1),")",p(")",!1),"%",p("%",!1),function(){return" "},function(){return":"},/^[!-~]/,$([["!","~"]],!1,!1),/^[\x80-\uFFFF]/,$([["",""]],!1,!1),/^[\x80-\xBF]/,$([["","¿"]],!1,!1),/^[a-f]/,$([["a","f"]],!1,!1),"`",p("`",!1),"<",p("<",!1),">",p(">",!1),"\\",p("\\",!1),"[",p("[",!1),"]",p("]",!1),"{",p("{",!1),"}",p("}",!1),function(){return"*"},function(){return"/"},function(){return"="},function(){return"("},function(){return")"},function(){return">"},function(){return"<"},function(){return","},function(){return";"},function(){return":"},function(){return'"'},/^[!-']/,$([["!","'"]],!1,!1),/^[*-[]/,$([["*","["]],!1,!1),/^[\]-~]/,$([["]","~"]],!1,!1),function(l){return l},/^[#-[]/,$([["#","["]],!1,!1),/^[\0-\t]/,$([["\0"," "]],!1,!1),/^[\v-\f]/,$([["\v","\f"]],!1,!1),/^[\x0E-\x7F]/,$([["",""]],!1,!1),function(){e=e||{data:{}},e.data.uri=new z(e.data.scheme,e.data.user,e.data.host,e.data.port),delete e.data.scheme,delete e.data.user,delete e.data.host,delete e.data.host_type,delete e.data.port},function(){e=e||{data:{}},e.data.uri=new z(e.data.scheme,e.data.user,e.data.host,e.data.port,e.data.uri_params,e.data.uri_headers),delete e.data.scheme,delete e.data.user,delete e.data.host,delete e.data.host_type,delete e.data.port,delete e.data.uri_params,e.startRule==="SIP_URI"&&(e.data=e.data.uri)},"sips",p("sips",!0),"sip",p("sip",!0),function(l){e=e||{data:{}},e.data.scheme=l},function(){e=e||{data:{}},e.data.user=decodeURIComponent(E().slice(0,-1))},function(){e=e||{data:{}},e.data.password=E()},function(){return e=e||{data:{}},e.data.host=E(),e.data.host},function(){return e=e||{data:{}},e.data.host_type="domain",E()},/^[a-zA-Z0-9_\-]/,$([["a","z"],["A","Z"],["0","9"],"_","-"],!1,!1),/^[a-zA-Z0-9\-]/,$([["a","z"],["A","Z"],["0","9"],"-"],!1,!1),function(){return e=e||{data:{}},e.data.host_type="IPv6",E()},"::",p("::",!1),function(){return e=e||{data:{}},e.data.host_type="IPv6",E()},function(){return e=e||{data:{}},e.data.host_type="IPv4",E()},"25",p("25",!1),/^[0-5]/,$([["0","5"]],!1,!1),"2",p("2",!1),/^[0-4]/,$([["0","4"]],!1,!1),"1",p("1",!1),/^[1-9]/,$([["1","9"]],!1,!1),function(l){return e=e||{data:{}},l=parseInt(l.join("")),e.data.port=l,l},"transport=",p("transport=",!0),"udp",p("udp",!0),"tcp",p("tcp",!0),"sctp",p("sctp",!0),"tls",p("tls",!0),function(l){e=e||{data:{}},e.data.uri_params||(e.data.uri_params={}),e.data.uri_params.transport=l.toLowerCase()},"user=",p("user=",!0),"phone",p("phone",!0),"ip",p("ip",!0),function(l){e=e||{data:{}},e.data.uri_params||(e.data.uri_params={}),e.data.uri_params.user=l.toLowerCase()},"method=",p("method=",!0),function(l){e=e||{data:{}},e.data.uri_params||(e.data.uri_params={}),e.data.uri_params.method=l},"ttl=",p("ttl=",!0),function(l){e=e||{data:{}},e.data.params||(e.data.params={}),e.data.params.ttl=l},"maddr=",p("maddr=",!0),function(l){e=e||{data:{}},e.data.uri_params||(e.data.uri_params={}),e.data.uri_params.maddr=l},"lr",p("lr",!0),function(){e=e||{data:{}},e.data.uri_params||(e.data.uri_params={}),e.data.uri_params.lr=void 0},function(l,y){e=e||{data:{}},e.data.uri_params||(e.data.uri_params={}),y===null?y=void 0:y=y[1],e.data.uri_params[l.toLowerCase()]=y},function(l,y){l=l.join("").toLowerCase(),y=y.join(""),e=e||{data:{}},e.data.uri_headers||(e.data.uri_headers={}),e.data.uri_headers[l]?e.data.uri_headers[l].push(y):e.data.uri_headers[l]=[y]},function(){e=e||{data:{}},e.startRule==="Refer_To"&&(e.data.uri=new z(e.data.scheme,e.data.user,e.data.host,e.data.port,e.data.uri_params,e.data.uri_headers),delete e.data.scheme,delete e.data.user,delete e.data.host,delete e.data.host_type,delete e.data.port,delete e.data.uri_params)},"//",p("//",!1),function(){e=e||{data:{}},e.data.scheme=E()},p("SIP",!0),function(){e=e||{data:{}},e.data.sip_version=E()},"INVITE",p("INVITE",!1),"ACK",p("ACK",!1),"VXACH",p("VXACH",!1),"OPTIONS",p("OPTIONS",!1),"BYE",p("BYE",!1),"CANCEL",p("CANCEL",!1),"REGISTER",p("REGISTER",!1),"SUBSCRIBE",p("SUBSCRIBE",!1),"NOTIFY",p("NOTIFY",!1),"REFER",p("REFER",!1),"PUBLISH",p("PUBLISH",!1),function(){return e=e||{data:{}},e.data.method=E(),e.data.method},function(l){e=e||{data:{}},e.data.status_code=parseInt(l.join(""))},function(){e=e||{data:{}},e.data.reason_phrase=E()},function(){e=e||{data:{}},e.data=E()},function(){var l,y;for(e=e||{data:{}},y=e.data.multi_header.length,l=0;l<y;l++)if(e.data.multi_header[l].parsed===null){e.data=null;break}e.data!==null?e.data=e.data.multi_header:e.data=-1},function(){var l;e=e||{data:{}},e.data.multi_header||(e.data.multi_header=[]);try{l=new N(e.data.uri,e.data.displayName,e.data.params),delete e.data.uri,delete e.data.displayName,delete e.data.params}catch{l=null}e.data.multi_header.push({position:d,offset:ge().start.offset,parsed:l})},function(l){l=E().trim(),l[0]==='"'&&(l=l.substring(1,l.length-1)),e=e||{data:{}},e.data.displayName=l},"q",p("q",!0),function(l){e=e||{data:{}},e.data.params||(e.data.params={}),e.data.params.q=l},"expires",p("expires",!0),function(l){e=e||{data:{}},e.data.params||(e.data.params={}),e.data.params.expires=l},function(l){return parseInt(l.join(""))},"0",p("0",!1),function(){return parseFloat(E())},function(l,y){e=e||{data:{}},e.data.params||(e.data.params={}),y===null?y=void 0:y=y[1],e.data.params[l.toLowerCase()]=y},"render",p("render",!0),"session",p("session",!0),"icon",p("icon",!0),"alert",p("alert",!0),function(){e=e||{data:{}},e.startRule==="Content_Disposition"&&(e.data.type=E().toLowerCase())},"handling",p("handling",!0),"optional",p("optional",!0),"required",p("required",!0),function(l){e=e||{data:{}},e.data=parseInt(l.join(""))},function(){e=e||{data:{}},e.data=E()},"text",p("text",!0),"image",p("image",!0),"audio",p("audio",!0),"video",p("video",!0),"application",p("application",!0),"message",p("message",!0),"multipart",p("multipart",!0),"x-",p("x-",!0),function(l){e=e||{data:{}},e.data.value=parseInt(l.join(""))},function(l){e=e||{data:{}},e.data=l},function(l){e=e||{data:{}},e.data.event=l.toLowerCase()},function(){e=e||{data:{}};var l=e.data.tag;e.data=new N(e.data.uri,e.data.displayName,e.data.params),l&&e.data.setParam("tag",l)},"tag",p("tag",!0),function(l){e=e||{data:{}},e.data.tag=l},function(l){e=e||{data:{}},e.data=parseInt(l.join(""))},function(l){e=e||{data:{}},e.data=l},function(){e=e||{data:{}},e.data=new N(e.data.uri,e.data.displayName,e.data.params)},"digest",p("Digest",!0),"realm",p("realm",!0),function(l){e=e||{data:{}},e.data.realm=l},"domain",p("domain",!0),"nonce",p("nonce",!0),function(l){e=e||{data:{}},e.data.nonce=l},"opaque",p("opaque",!0),function(l){e=e||{data:{}},e.data.opaque=l},"stale",p("stale",!0),"true",p("true",!0),function(){e=e||{data:{}},e.data.stale=!0},"false",p("false",!0),function(){e=e||{data:{}},e.data.stale=!1},"algorithm",p("algorithm",!0),"md5",p("MD5",!0),"md5-sess",p("MD5-sess",!0),function(l){e=e||{data:{}},e.data.algorithm=l.toUpperCase()},"qop",p("qop",!0),"auth-int",p("auth-int",!0),"auth",p("auth",!0),function(l){e=e||{data:{}},e.data.qop||(e.data.qop=[]),e.data.qop.push(l.toLowerCase())},function(l){e=e||{data:{}},e.data.value=parseInt(l.join(""))},function(){var l,y;for(e=e||{data:{}},y=e.data.multi_header.length,l=0;l<y;l++)if(e.data.multi_header[l].parsed===null){e.data=null;break}e.data!==null?e.data=e.data.multi_header:e.data=-1},function(){var l;e=e||{data:{}},e.data.multi_header||(e.data.multi_header=[]);try{l=new N(e.data.uri,e.data.displayName,e.data.params),delete e.data.uri,delete e.data.displayName,delete e.data.params}catch{l=null}e.data.multi_header.push({position:d,offset:ge().start.offset,parsed:l})},function(){e=e||{data:{}},e.data=new N(e.data.uri,e.data.displayName,e.data.params)},function(){e=e||{data:{}},e.data.replaces_from_tag&&e.data.replaces_to_tag||(e.data=-1)},function(){e=e||{data:{}},e.data={call_id:e.data}},"from-tag",p("from-tag",!0),function(l){e=e||{data:{}},e.data.replaces_from_tag=l},"to-tag",p("to-tag",!0),function(l){e=e||{data:{}},e.data.replaces_to_tag=l},"early-only",p("early-only",!0),function(){e=e||{data:{}},e.data.early_only=!0},function(l,y){return y},function(l,y){return Bi(l,y)},function(l){e=e||{data:{}},e.startRule==="Require"&&(e.data=l||[])},function(l){e=e||{data:{}},e.data.value=parseInt(l.join(""))},"active",p("active",!0),"pending",p("pending",!0),"terminated",p("terminated",!0),function(){e=e||{data:{}},e.data.state=E()},"reason",p("reason",!0),function(l){e=e||{data:{}},typeof l<"u"&&(e.data.reason=l)},function(l){e=e||{data:{}},typeof l<"u"&&(e.data.expires=l)},"retry_after",p("retry_after",!0),function(l){e=e||{data:{}},typeof l<"u"&&(e.data.retry_after=l)},"deactivated",p("deactivated",!0),"probation",p("probation",!0),"rejected",p("rejected",!0),"timeout",p("timeout",!0),"giveup",p("giveup",!0),"noresource",p("noresource",!0),"invariant",p("invariant",!0),function(l){e=e||{data:{}},e.startRule==="Supported"&&(e.data=l||[])},function(){e=e||{data:{}};var l=e.data.tag;e.data=new N(e.data.uri,e.data.displayName,e.data.params),l&&e.data.setParam("tag",l)},"ttl",p("ttl",!0),function(l){e=e||{data:{}},e.data.ttl=l},"maddr",p("maddr",!0),function(l){e=e||{data:{}},e.data.maddr=l},"received",p("received",!0),function(l){e=e||{data:{}},e.data.received=l},"branch",p("branch",!0),function(l){e=e||{data:{}},e.data.branch=l},"rport",p("rport",!0),function(l){e=e||{data:{}},typeof l<"u"&&(e.data.rport=l.join(""))},function(l){e=e||{data:{}},e.data.protocol=l},p("UDP",!0),p("TCP",!0),p("TLS",!0),p("SCTP",!0),function(l){e=e||{data:{}},e.data.transport=l},function(){e=e||{data:{}},e.data.host=E()},function(l){e=e||{data:{}},e.data.port=parseInt(l.join(""))},function(l){return parseInt(l.join(""))},function(l){e=e||{data:{}},e.startRule==="Session_Expires"&&(e.data.deltaSeconds=l)},"refresher",p("refresher",!1),"uas",p("uas",!1),"uac",p("uac",!1),function(l){e=e||{data:{}},e.startRule==="Session_Expires"&&(e.data.refresher=l)},function(l){e=e||{data:{}},e.startRule==="Min_SE"&&(e.data=l)},"stuns",p("stuns",!0),"stun",p("stun",!0),function(l){e=e||{data:{}},e.data.scheme=l},function(l){e=e||{data:{}},e.data.host=l},"?transport=",p("?transport=",!1),"turns",p("turns",!0),"turn",p("turn",!0),function(l){e=e||{data:{}},e.data.transport=l},function(){e=e||{data:{}},e.data=E()},"Referred-By",p("Referred-By",!1),"b",p("b",!1),"cid",p("cid",!1)],a=[c('2 ""6 7!'),c('4"""5!7#'),c('4$""5!7%'),c(`4&""5!7'`),c(";'.# &;("),c('4(""5!7)'),c('4*""5!7+'),c('2,""6,7-'),c('2.""6.7/'),c('40""5!71'),c('22""6273. &24""6475.} &26""6677.q &28""6879.e &2:""6:7;.Y &2<""6<7=.M &2>""6>7?.A &2@""6@7A.5 &2B""6B7C.) &2D""6D7E'),c(";).# &;,"),c('2F""6F7G.} &2H""6H7I.q &2J""6J7K.e &2L""6L7M.Y &2N""6N7O.M &2P""6P7Q.A &2R""6R7S.5 &2T""6T7U.) &2V""6V7W'),c(`%%2X""6X7Y/5#;#/,$;#/#$+#)(#'#("'#&'#/"!&,)`),c(`%%$;$0#*;$&/,#; /#$+")("'#&'#." &"/=#$;$/�#*;$&&&#/'$8":Z" )("'#&'#`),c(';.." &"'),c(`%$;'.# &;(0)*;'.# &;(&/?#28""6879/0$;//'$8#:[# )(#'#("'#&'#`),c(`%%$;2/�#*;2&&&#/g#$%$;.0#*;.&/,#;2/#$+")("'#&'#0=*%$;.0#*;.&/,#;2/#$+")("'#&'#&/#$+")("'#&'#/"!&,)`),c('4\\""5!7].# &;3'),c('4^""5!7_'),c('4`""5!7a'),c(';!.) &4b""5!7c'),c('%$;). &2F""6F7G. &2J""6J7K.} &2L""6L7M.q &2X""6X7Y.e &2P""6P7Q.Y &2H""6H7I.M &2@""6@7A.A &2d""6d7e.5 &2R""6R7S.) &2N""6N7O/#0*;). &2F""6F7G. &2J""6J7K.} &2L""6L7M.q &2X""6X7Y.e &2P""6P7Q.Y &2H""6H7I.M &2@""6@7A.A &2d""6d7e.5 &2R""6R7S.) &2N""6N7O&&&#/"!&,)'),c('%$;). &2F""6F7G.} &2L""6L7M.q &2X""6X7Y.e &2P""6P7Q.Y &2H""6H7I.M &2@""6@7A.A &2d""6d7e.5 &2R""6R7S.) &2N""6N7O/#0*;). &2F""6F7G.} &2L""6L7M.q &2X""6X7Y.e &2P""6P7Q.Y &2H""6H7I.M &2@""6@7A.A &2d""6d7e.5 &2R""6R7S.) &2N""6N7O&&&#/"!&,)'),c(`2T""6T7U.ã &2V""6V7W.× &2f""6f7g.Ë &2h""6h7i.¿ &2:""6:7;.³ &2D""6D7E.§ &22""6273. &28""6879. &2j""6j7k. &;&.} &24""6475.q &2l""6l7m.e &2n""6n7o.Y &26""6677.M &2>""6>7?.A &2p""6p7q.5 &2r""6r7s.) &;'.# &;(`),c('%$;).ī &2F""6F7G.ğ &2J""6J7K.ē &2L""6L7M.ć &2X""6X7Y.û &2P""6P7Q.ï &2H""6H7I.ã &2@""6@7A.× &2d""6d7e.Ë &2R""6R7S.¿ &2N""6N7O.³ &2T""6T7U.§ &2V""6V7W. &2f""6f7g. &2h""6h7i. &28""6879.w &2j""6j7k.k &;&.e &24""6475.Y &2l""6l7m.M &2n""6n7o.A &26""6677.5 &2p""6p7q.) &2r""6r7s/Ĵ#0ı*;).ī &2F""6F7G.ğ &2J""6J7K.ē &2L""6L7M.ć &2X""6X7Y.û &2P""6P7Q.ï &2H""6H7I.ã &2@""6@7A.× &2d""6d7e.Ë &2R""6R7S.¿ &2N""6N7O.³ &2T""6T7U.§ &2V""6V7W. &2f""6f7g. &2h""6h7i. &28""6879.w &2j""6j7k.k &;&.e &24""6475.Y &2l""6l7m.M &2n""6n7o.A &26""6677.5 &2p""6p7q.) &2r""6r7s&&&#/"!&,)'),c(`%;//?#2P""6P7Q/0$;//'$8#:t# )(#'#("'#&'#`),c(`%;//?#24""6475/0$;//'$8#:u# )(#'#("'#&'#`),c(`%;//?#2>""6>7?/0$;//'$8#:v# )(#'#("'#&'#`),c(`%;//?#2T""6T7U/0$;//'$8#:w# )(#'#("'#&'#`),c(`%;//?#2V""6V7W/0$;//'$8#:x# )(#'#("'#&'#`),c(`%2h""6h7i/0#;//'$8":y" )("'#&'#`),c(`%;//6#2f""6f7g/'$8":z" )("'#&'#`),c(`%;//?#2D""6D7E/0$;//'$8#:{# )(#'#("'#&'#`),c(`%;//?#22""6273/0$;//'$8#:|# )(#'#("'#&'#`),c(`%;//?#28""6879/0$;//'$8#:}# )(#'#("'#&'#`),c(`%;//0#;&/'$8":~" )("'#&'#`),c(`%;&/0#;//'$8":~" )("'#&'#`),c(`%;=/T#$;G.) &;K.# &;F0/*;G.) &;K.# &;F&/,$;>/#$+#)(#'#("'#&'#`),c('4""5!7.A &4""5!7.5 &4""5!7.) &;3.# &;.'),c(`%%;//Q#;&/H$$;J.# &;K0)*;J.# &;K&/,$;&/#$+$)($'#(#'#("'#&'#/"!&,)`),c(`%;//]#;&/T$%$;J.# &;K0)*;J.# &;K&/"!&,)/1$;&/($8$:
$!!)($'#(#'#("'#&'#`),c(';..G &2L""6L7M.; &4""5!7./ &4""5!7.# &;3'),c(`%2j""6j7k/J#4""5!7.5 &4""5!7.) &4""5!7/#$+")("'#&'#`),c(`%;N/M#28""6879/>$;O." &"/0$;S/'$8$:$ )($'#(#'#("'#&'#`),c(`%;N/d#28""6879/U$;O." &"/G$;S/>$;_/5$;l." &"/'$8&:& )(&'#(%'#($'#(#'#("'#&'#`),c(`%3""5$7.) &3""5#7/' 8!:!! )`),c(`%;P/]#%28""6879/,#;R/#$+")("'#&'#." &"/6$2:""6:7;/'$8#:# )(#'#("'#&'#`),c("$;+.) &;-.# &;Q/2#0/*;+.) &;-.# &;Q&&&#"),c('2<""6<7=.q &2>""6>7?.e &2@""6@7A.Y &2B""6B7C.M &2D""6D7E.A &22""6273.5 &26""6677.) &24""6475'),c('%$;+._ &;-.Y &2<""6<7=.M &2>""6>7?.A &2@""6@7A.5 &2B""6B7C.) &2D""6D7E0e*;+._ &;-.Y &2<""6<7=.M &2>""6>7?.A &2@""6@7A.5 &2B""6B7C.) &2D""6D7E&/& 8!:! )'),c(`%;T/J#%28""6879/,#;^/#$+")("'#&'#." &"/#$+")("'#&'#`),c("%;U.) &;\\.# &;X/& 8!:! )"),c(`%$%;V/2#2J""6J7K/#$+")("'#&'#0<*%;V/2#2J""6J7K/#$+")("'#&'#&/D#;W/;$2J""6J7K." &"/'$8#:# )(#'#("'#&'#`),c('$4""5!7/,#0)*4""5!7&&&#'),c(`%4$""5!7%/?#$4""5!70)*4""5!7&/#$+")("'#&'#`),c(`%2l""6l7m/?#;Y/6$2n""6n7o/'$8#:# )(#'#("'#&'#`),c(`%%;Z/³#28""6879/¤$;Z/$28""6879/$;Z/$28""6879/t$;Z/k$28""6879/\\$;Z/S$28""6879/D$;Z/;$28""6879/,$;[/#$+-)(-'#(,'#(+'#(*'#()'#(('#(''#(&'#(%'#($'#(#'#("'#&'#.ސ &%2""67/¤#;Z/$28""6879/$;Z/$28""6879/t$;Z/k$28""6879/\\$;Z/S$28""6879/D$;Z/;$28""6879/,$;[/#$+,)(,'#(+'#(*'#()'#(('#(''#(&'#(%'#($'#(#'#("'#&'#.۹ &%2""67/#;Z/$28""6879/t$;Z/k$28""6879/\\$;Z/S$28""6879/D$;Z/;$28""6879/,$;[/#$+*)(*'#()'#(('#(''#(&'#(%'#($'#(#'#("'#&'#.ٺ &%2""67/t#;Z/k$28""6879/\\$;Z/S$28""6879/D$;Z/;$28""6879/,$;[/#$+()(('#(''#(&'#(%'#($'#(#'#("'#&'#.ؓ &%2""67/\\#;Z/S$28""6879/D$;Z/;$28""6879/,$;[/#$+&)(&'#(%'#($'#(#'#("'#&'#.ׄ &%2""67/D#;Z/;$28""6879/,$;[/#$+$)($'#(#'#("'#&'#.֍ &%2""67/,#;[/#$+")("'#&'#.ծ &%2""67/,#;Z/#$+")("'#&'#.Տ &%;Z/#2""67/$;Z/$28""6879/t$;Z/k$28""6879/\\$;Z/S$28""6879/D$;Z/;$28""6879/,$;[/#$++)(+'#(*'#()'#(('#(''#(&'#(%'#($'#(#'#("'#&'#.Ӈ &%;Z/ª#%28""6879/,#;Z/#$+")("'#&'#." &"/$2""67/t$;Z/k$28""6879/\\$;Z/S$28""6879/D$;Z/;$28""6879/,$;[/#$+*)(*'#()'#(('#(''#(&'#(%'#($'#(#'#("'#&'#.а &%;Z/¹#%28""6879/,#;Z/#$+")("'#&'#." &"/$%28""6879/,#;Z/#$+")("'#&'#." &"/k$2""67/\\$;Z/S$28""6879/D$;Z/;$28""6879/,$;[/#$+))()'#(('#(''#(&'#(%'#($'#(#'#("'#&'#.Ί &%;Z/È#%28""6879/,#;Z/#$+")("'#&'#." &"/¡$%28""6879/,#;Z/#$+")("'#&'#." &"/z$%28""6879/,#;Z/#$+")("'#&'#." &"/S$2""67/D$;Z/;$28""6879/,$;[/#$+()(('#(''#(&'#(%'#($'#(#'#("'#&'#.˕ &%;Z/×#%28""6879/,#;Z/#$+")("'#&'#." &"/°$%28""6879/,#;Z/#$+")("'#&'#." &"/$%28""6879/,#;Z/#$+")("'#&'#." &"/b$%28""6879/,#;Z/#$+")("'#&'#." &"/;$2""67/,$;[/#$+')(''#(&'#(%'#($'#(#'#("'#&'#.ȑ &%;Z/þ#%28""6879/,#;Z/#$+")("'#&'#." &"/×$%28""6879/,#;Z/#$+")("'#&'#." &"/°$%28""6879/,#;Z/#$+")("'#&'#." &"/$%28""6879/,#;Z/#$+")("'#&'#." &"/b$%28""6879/,#;Z/#$+")("'#&'#." &"/;$2""67/,$;Z/#$+()(('#(''#(&'#(%'#($'#(#'#("'#&'#.Ħ &%;Z/Ĝ#%28""6879/,#;Z/#$+")("'#&'#." &"/õ$%28""6879/,#;Z/#$+")("'#&'#." &"/Î$%28""6879/,#;Z/#$+")("'#&'#." &"/§$%28""6879/,#;Z/#$+")("'#&'#." &"/$%28""6879/,#;Z/#$+")("'#&'#." &"/Y$%28""6879/,#;Z/#$+")("'#&'#." &"/2$2""67/#$+()(('#(''#(&'#(%'#($'#(#'#("'#&'#/& 8!: ! )`),c(`%;#/M#;#." &"/?$;#." &"/1$;#." &"/#$+$)($'#(#'#("'#&'#`),c(`%;Z/;#28""6879/,$;Z/#$+#)(#'#("'#&'#.# &;\\`),c(`%;]/o#2J""6J7K/\`$;]/W$2J""6J7K/H$;]/?$2J""6J7K/0$;]/'$8':¡' )(''#(&'#(%'#($'#(#'#("'#&'#`),c(`%2¢""6¢7£/2#4¤""5!7¥/#$+")("'#&'#. &%2¦""6¦7§/;#4¨""5!7©/,$;!/#$+#)(#'#("'#&'#.j &%2ª""6ª7«/5#;!/,$;!/#$+#)(#'#("'#&'#.B &%4¬""5!7/,#;!/#$+")("'#&'#.# &;!`),c(`%%;!." &"/[#;!." &"/M$;!." &"/?$;!." &"/1$;!." &"/#$+%)(%'#($'#(#'#("'#&'#/' 8!:®!! )`),c(`$%22""6273/,#;\`/#$+")("'#&'#0<*%22""6273/,#;\`/#$+")("'#&'#&`),c(";a.A &;b.; &;c.5 &;d./ &;e.) &;f.# &;g"),c(`%3¯""5*7°/a#3±""5#7².G &3³""5#7´.; &3µ""5$7¶./ &3·""5#7¸.# &;6/($8":¹"! )("'#&'#`),c(`%3º""5%7»/I#3¼""5%7½./ &3¾""5"7¿.# &;6/($8":À"! )("'#&'#`),c(`%3Á""5'7Â/1#;/($8":Ã"! )("'#&'#`),c(`%3Ä""5$7Å/1#;ð/($8":Æ"! )("'#&'#`),c(`%3Ç""5&7È/1#;T/($8":É"! )("'#&'#`),c(`%3Ê""5"7Ë/N#%2>""6>7?/,#;6/#$+")("'#&'#." &"/'$8":Ì" )("'#&'#`),c(`%;h/P#%2>""6>7?/,#;i/#$+")("'#&'#." &"/)$8":Í""! )("'#&'#`),c('%$;j/�#*;j&&&#/"!&,)'),c('%$;j/�#*;j&&&#/"!&,)'),c(";k.) &;+.# &;-"),c('2l""6l7m.e &2n""6n7o.Y &24""6475.M &28""6879.A &2<""6<7=.5 &2@""6@7A.) &2B""6B7C'),c(`%26""6677/n#;m/e$$%2<""6<7=/,#;m/#$+")("'#&'#0<*%2<""6<7=/,#;m/#$+")("'#&'#&/#$+#)(#'#("'#&'#`),c(`%;n/A#2>""6>7?/2$;o/)$8#:Î#"" )(#'#("'#&'#`),c("$;p.) &;+.# &;-/2#0/*;p.) &;+.# &;-&&&#"),c("$;p.) &;+.# &;-0/*;p.) &;+.# &;-&"),c('2l""6l7m.e &2n""6n7o.Y &24""6475.M &26""6677.A &28""6879.5 &2@""6@7A.) &2B""6B7C'),c(";.# &;r"),c(`%;/G#;'/>$;s/5$;'/,$;/#$+%)(%'#($'#(#'#("'#&'#`),c(";M.# &;t"),c(`%;/E#28""6879/6$;u.# &;x/'$8#:Ï# )(#'#("'#&'#`),c(`%;v.# &;w/J#%26""6677/,#;/#$+")("'#&'#." &"/#$+")("'#&'#`),c(`%2Ð""6Ð7Ñ/:#;/1$;w." &"/#$+#)(#'#("'#&'#`),c(`%24""6475/,#;{/#$+")("'#&'#`),c(`%;z/3#$;y0#*;y&/#$+")("'#&'#`),c(";*.) &;+.# &;-"),c(';+. &;-. &22""6273.} &26""6677.q &28""6879.e &2:""6:7;.Y &2<""6<7=.M &2>""6>7?.A &2@""6@7A.5 &2B""6B7C.) &2D""6D7E'),c(`%;|/e#$%24""6475/,#;|/#$+")("'#&'#0<*%24""6475/,#;|/#$+")("'#&'#&/#$+")("'#&'#`),c(`%$;~0#*;~&/e#$%22""6273/,#;}/#$+")("'#&'#0<*%22""6273/,#;}/#$+")("'#&'#&/#$+")("'#&'#`),c("$;~0#*;~&"),c(';+.w &;-.q &28""6879.e &2:""6:7;.Y &2<""6<7=.M &2>""6>7?.A &2@""6@7A.5 &2B""6B7C.) &2D""6D7E'),c(`%%;"/#$;".G &;!.A &2@""6@7A.5 &2F""6F7G.) &2J""6J7K0M*;".G &;!.A &2@""6@7A.5 &2F""6F7G.) &2J""6J7K&/#$+")("'#&'#/& 8!:Ò! )`),c(";.# &;"),c(`%%;O/2#2:""6:7;/#$+")("'#&'#." &"/,#;S/#$+")("'#&'#." &"`),c('$;+. &;-.} &2B""6B7C.q &2D""6D7E.e &22""6273.Y &28""6879.M &2:""6:7;.A &2<""6<7=.5 &2>""6>7?.) &2@""6@7A/#0*;+. &;-.} &2B""6B7C.q &2D""6D7E.e &22""6273.Y &28""6879.M &2:""6:7;.A &2<""6<7=.5 &2>""6>7?.) &2@""6@7A&&&#'),c("$;y0#*;y&"),c(`%3""5#7Ó/q#24""6475/b$$;!/�#*;!&&&#/L$2J""6J7K/=$$;!/�#*;!&&&#/'$8%:Ô% )(%'#($'#(#'#("'#&'#`),c('2Õ""6Õ7Ö'),c('2×""6×7Ø'),c('2Ù""6Ù7Ú'),c('2Û""6Û7Ü'),c('2Ý""6Ý7Þ'),c('2ß""6ß7à'),c('2á""6á7â'),c('2ã""6ã7ä'),c('2å""6å7æ'),c('2ç""6ç7è'),c('2é""6é7ê'),c("%;
.Y &;.S &;.M &;.G &;.A &;.; &;.5 &;./ &;.) &;.# &;6/& 8!:ë! )"),c(`%;/G#;'/>$;/5$;'/,$;/#$+%)(%'#($'#(#'#("'#&'#`),c("%;/' 8!:ì!! )"),c(`%;!/5#;!/,$;!/#$+#)(#'#("'#&'#`),c("%$;*.A &;+.; &;-.5 &;3./ &;4.) &;'.# &;(0G*;*.A &;+.; &;-.5 &;3./ &;4.) &;'.# &;(&/& 8!:í! )"),c(`%;¶/Y#$%;A/,#;¶/#$+")("'#&'#06*%;A/,#;¶/#$+")("'#&'#&/#$+")("'#&'#`),c(`%;9/N#%2:""6:7;/,#;9/#$+")("'#&'#." &"/'$8":î" )("'#&'#`),c(`%;:.c &%;/Y#$%;A/,#;/#$+")("'#&'#06*%;A/,#;/#$+")("'#&'#&/#$+")("'#&'#/& 8!:ï! )`),c(`%;L.# &;/]#$%;B/,#;/#$+")("'#&'#06*%;B/,#;/#$+")("'#&'#&/'$8":ð" )("'#&'#`),c(`%;." &"/>#;@/5$;M/,$;?/#$+$)($'#(#'#("'#&'#`),c(`%%;6/Y#$%;./,#;6/#$+")("'#&'#06*%;./,#;6/#$+")("'#&'#&/#$+")("'#&'#.# &;H/' 8!:ñ!! )`),c(";.) &;.# &; "),c(`%3ò""5!7ó/:#;</1$;/($8#:ô#! )(#'#("'#&'#`),c(`%3õ""5'7ö/:#;</1$;/($8#:÷#! )(#'#("'#&'#`),c("%$;!/�#*;!&&&#/' 8!:ø!! )"),c(`%2ù""6ù7ú/o#%2J""6J7K/M#;!." &"/?$;!." &"/1$;!." &"/#$+$)($'#(#'#("'#&'#." &"/'$8":û" )("'#&'#`),c(`%;6/J#%;</,#;¡/#$+")("'#&'#." &"/)$8":ü""! )("'#&'#`),c(";6.) &;T.# &;H"),c(`%;£/Y#$%;B/,#;¤/#$+")("'#&'#06*%;B/,#;¤/#$+")("'#&'#&/#$+")("'#&'#`),c(`%3ý""5&7þ.G &3ÿ""5'7Ā.; &3ā""5$7Ă./ &3ă""5%7Ą.# &;6/& 8!:ą! )`),c(";¥.# &; "),c(`%3Ć""5(7ć/M#;</D$3Ĉ""5(7ĉ./ &3Ċ""5(7ċ.# &;6/#$+#)(#'#("'#&'#`),c(`%;6/Y#$%;A/,#;6/#$+")("'#&'#06*%;A/,#;6/#$+")("'#&'#&/#$+")("'#&'#`),c("%$;!/�#*;!&&&#/' 8!:Č!! )"),c("%;©/& 8!:č! )"),c(`%;ª/k#;;/b$;¯/Y$$%;B/,#;°/#$+")("'#&'#06*%;B/,#;°/#$+")("'#&'#&/#$+$)($'#(#'#("'#&'#`),c(";«.# &;¬"),c('3Ď""5$7ď.S &3Đ""5%7đ.G &3Ē""5%7ē.; &3Ĕ""5%7ĕ./ &3Ė""5+7ė.# &;'),c(`3Ę""5'7ę./ &3Ě""5)7ě.# &;`),c(";6.# &;®"),c(`%3Ĝ""5"7ĝ/,#;6/#$+")("'#&'#`),c(";.# &;6"),c(`%;6/5#;</,$;±/#$+#)(#'#("'#&'#`),c(";6.# &;H"),c(`%;³/5#;./,$;/#$+#)(#'#("'#&'#`),c("%$;!/�#*;!&&&#/' 8!:Ğ!! )"),c("%;/' 8!:ğ!! )"),c(`%;¶/^#$%;B/,#; /#$+")("'#&'#06*%;B/,#; /#$+")("'#&'#&/($8":Ġ"!!)("'#&'#`),c(`%%;7/e#$%2J""6J7K/,#;7/#$+")("'#&'#0<*%2J""6J7K/,#;7/#$+")("'#&'#&/#$+")("'#&'#/"!&,)`),c(`%;L.# &;/]#$%;B/,#;¸/#$+")("'#&'#06*%;B/,#;¸/#$+")("'#&'#&/'$8":ġ" )("'#&'#`),c(";¹.# &; "),c(`%3Ģ""5#7ģ/:#;</1$;6/($8#:Ĥ#! )(#'#("'#&'#`),c("%$;!/�#*;!&&&#/' 8!:ĥ!! )"),c("%;/' 8!:Ħ!! )"),c(`%$;0#*;&/x#;@/o$;M/f$;?/]$$%;B/,#; /#$+")("'#&'#06*%;B/,#; /#$+")("'#&'#&/'$8%:ħ% )(%'#($'#(#'#("'#&'#`),c(";¾"),c(`%3Ĩ""5&7ĩ/k#;./b$;Á/Y$$%;A/,#;Á/#$+")("'#&'#06*%;A/,#;Á/#$+")("'#&'#&/#$+$)($'#(#'#("'#&'#.# &;¿`),c(`%;6/k#;./b$;À/Y$$%;A/,#;À/#$+")("'#&'#06*%;A/,#;À/#$+")("'#&'#&/#$+$)($'#(#'#("'#&'#`),c(`%;6/;#;</2$;6.# &;H/#$+#)(#'#("'#&'#`),c(";Â.G &;Ä.A &;Æ.; &;È.5 &;É./ &;Ê.) &;Ë.# &;À"),c(`%3Ī""5%7ī/5#;</,$;Ã/#$+#)(#'#("'#&'#`),c("%;I/' 8!:Ĭ!! )"),c(`%3ĭ""5&7Į/#;</$;D/
$;Å/|$$%$;'/�#*;'&&&#/,#;Å/#$+")("'#&'#0C*%$;'/�#*;'&&&#/,#;Å/#$+")("'#&'#&/,$;E/#$+&)(&'#(%'#($'#(#'#("'#&'#`),c(";t.# &;w"),c(`%3į""5%7İ/5#;</,$;Ç/#$+#)(#'#("'#&'#`),c("%;I/' 8!:ı!! )"),c(`%3IJ""5&7ij/:#;</1$;I/($8#:Ĵ#! )(#'#("'#&'#`),c(`%3ĵ""5%7Ķ/]#;</T$%3ķ""5$7ĸ/& 8!:Ĺ! ).4 &%3ĺ""5%7Ļ/& 8!:ļ! )/#$+#)(#'#("'#&'#`),c(`%3Ľ""5)7ľ/R#;</I$3Ŀ""5#7ŀ./ &3Ł""5(7ł.# &;6/($8#:Ń#! )(#'#("'#&'#`),c(`%3ń""5#7Ņ/#;</$;D/$%;Ì/e#$%2D""6D7E/,#;Ì/#$+")("'#&'#0<*%2D""6D7E/,#;Ì/#$+")("'#&'#&/#$+")("'#&'#/,$;E/#$+%)(%'#($'#(#'#("'#&'#`),c(`%3ņ""5(7Ň./ &3ň""5$7ʼn.# &;6/' 8!:Ŋ!! )`),c(`%;6/Y#$%;A/,#;6/#$+")("'#&'#06*%;A/,#;6/#$+")("'#&'#&/#$+")("'#&'#`),c(`%;Ï/G#;./>$;Ï/5$;./,$;/#$+%)(%'#($'#(#'#("'#&'#`),c("%$;!/�#*;!&&&#/' 8!:ŋ!! )"),c(`%;Ñ/]#$%;A/,#;Ñ/#$+")("'#&'#06*%;A/,#;Ñ/#$+")("'#&'#&/'$8":Ō" )("'#&'#`),c(`%;/]#$%;B/,#; /#$+")("'#&'#06*%;B/,#; /#$+")("'#&'#&/'$8":ō" )("'#&'#`),c(`%;L.O &;.I &%;@." &"/:#;t/1$;?." &"/#$+#)(#'#("'#&'#/]#$%;B/,#; /#$+")("'#&'#06*%;B/,#; /#$+")("'#&'#&/'$8":Ŏ" )("'#&'#`),c(`%;Ô/]#$%;B/,#;Õ/#$+")("'#&'#06*%;B/,#;Õ/#$+")("'#&'#&/'$8":ŏ" )("'#&'#`),c("%;/& 8!:Ő! )"),c(`%3ő""5(7Œ/:#;</1$;6/($8#:œ#! )(#'#("'#&'#.g &%3Ŕ""5&7ŕ/:#;</1$;6/($8#:Ŗ#! )(#'#("'#&'#.: &%3ŗ""5*7Ř/& 8!:ř! ).# &; `),c(`%%;6/k#$%;A/2#;6/)$8":Ś""$ )("'#&'#0<*%;A/2#;6/)$8":Ś""$ )("'#&'#&/)$8":ś""! )("'#&'#." &"/' 8!:Ŝ!! )`),c(`%;Ø/Y#$%;A/,#;Ø/#$+")("'#&'#06*%;A/,#;Ø/#$+")("'#&'#&/#$+")("'#&'#`),c(`%;/Y#$%;B/,#; /#$+")("'#&'#06*%;B/,#; /#$+")("'#&'#&/#$+")("'#&'#`),c("%$;!/�#*;!&&&#/' 8!:ŝ!! )"),c(`%;Û/Y#$%;B/,#;Ü/#$+")("'#&'#06*%;B/,#;Ü/#$+")("'#&'#&/#$+")("'#&'#`),c(`%3Ş""5&7ş.; &3Š""5'7š./ &3Ţ""5*7ţ.# &;6/& 8!:Ť! )`),c(`%3ť""5&7Ŧ/:#;</1$;Ý/($8#:ŧ#! )(#'#("'#&'#.} &%3õ""5'7ö/:#;</1$;/($8#:Ũ#! )(#'#("'#&'#.P &%3ũ""5+7Ū/:#;</1$;/($8#:ū#! )(#'#("'#&'#.# &; `),c(`3Ŭ""5+7ŭ.k &3Ů""5)7ů._ &3Ű""5(7ű.S &3Ų""5'7ų.G &3Ŵ""5&7ŵ.; &3Ŷ""5*7ŷ./ &3Ÿ""5)7Ź.# &;6`),c(';1." &"'),c(`%%;6/k#$%;A/2#;6/)$8":Ś""$ )("'#&'#0<*%;A/2#;6/)$8":Ś""$ )("'#&'#&/)$8":ś""! )("'#&'#." &"/' 8!:ź!! )`),c(`%;L.# &;/]#$%;B/,#;á/#$+")("'#&'#06*%;B/,#;á/#$+")("'#&'#&/'$8":Ż" )("'#&'#`),c(";¹.# &; "),c(`%;ã/Y#$%;A/,#;ã/#$+")("'#&'#06*%;A/,#;ã/#$+")("'#&'#&/#$+")("'#&'#`),c(`%;ê/k#;./b$;í/Y$$%;B/,#;ä/#$+")("'#&'#06*%;B/,#;ä/#$+")("'#&'#&/#$+$)($'#(#'#("'#&'#`),c(";å.; &;æ.5 &;ç./ &;è.) &;é.# &; "),c(`%3ż""5#7Ž/:#;</1$;ð/($8#:ž#! )(#'#("'#&'#`),c(`%3ſ""5%7ƀ/:#;</1$;T/($8#:Ɓ#! )(#'#("'#&'#`),c(`%3Ƃ""5(7ƃ/F#;</=$;\\.) &;Y.# &;X/($8#:Ƅ#! )(#'#("'#&'#`),c(`%3ƅ""5&7Ɔ/:#;</1$;6/($8#:Ƈ#! )(#'#("'#&'#`),c(`%3ƈ""5%7Ɖ/A#;</8$$;!0#*;!&/($8#:Ɗ#! )(#'#("'#&'#`),c(`%;ë/G#;;/>$;6/5$;;/,$;ì/#$+%)(%'#($'#(#'#("'#&'#`),c(`%3""5#7Ó.# &;6/' 8!:Ƌ!! )`),c(`%3±""5#7ƌ.G &3³""5#7ƍ.; &3·""5#7Ǝ./ &3µ""5$7Ə.# &;6/' 8!:Ɛ!! )`),c(`%;î/D#%;C/,#;ï/#$+")("'#&'#." &"/#$+")("'#&'#`),c("%;U.) &;\\.# &;X/& 8!:Ƒ! )"),c(`%%;!." &"/[#;!." &"/M$;!." &"/?$;!." &"/1$;!." &"/#$+%)(%'#($'#(#'#("'#&'#/' 8!:ƒ!! )`),c(`%%;!/?#;!." &"/1$;!." &"/#$+#)(#'#("'#&'#/' 8!:Ɠ!! )`),c(";¾"),c(`%;/^#$%;B/,#;ó/#$+")("'#&'#06*%;B/,#;ó/#$+")("'#&'#&/($8":Ɣ"!!)("'#&'#`),c(";ô.# &; "),c(`%2ƕ""6ƕ7Ɩ/L#;</C$2Ɨ""6Ɨ7Ƙ.) &2ƙ""6ƙ7ƚ/($8#:ƛ#! )(#'#("'#&'#`),c(`%;/^#$%;B/,#; /#$+")("'#&'#06*%;B/,#; /#$+")("'#&'#&/($8":Ɯ"!!)("'#&'#`),c(`%;6/5#;0/,$;÷/#$+#)(#'#("'#&'#`),c("$;2.) &;4.# &;.0/*;2.) &;4.# &;.&"),c("$;%0#*;%&"),c(`%;ú/;#28""6879/,$;û/#$+#)(#'#("'#&'#`),c(`%3Ɲ""5%7ƞ.) &3Ɵ""5$7Ơ/' 8!:ơ!! )`),c(`%;ü/J#%28""6879/,#;^/#$+")("'#&'#." &"/#$+")("'#&'#`),c("%;\\.) &;X.# &;/' 8!:Ƣ!! )"),c(';".S &;!.M &2F""6F7G.A &2J""6J7K.5 &2H""6H7I.) &2N""6N7O'),c('2L""6L7M. &2B""6B7C. &2<""6<7=.} &2R""6R7S.q &2T""6T7U.e &2V""6V7W.Y &2P""6P7Q.M &2@""6@7A.A &2D""6D7E.5 &22""6273.) &2>""6>7?'),c(`%;Ā/b#28""6879/S$;û/J$%2ƣ""6ƣ7Ƥ/,#;ì/#$+")("'#&'#." &"/#$+$)($'#(#'#("'#&'#`),c(`%3ƥ""5%7Ʀ.) &3Ƨ""5$7ƨ/' 8!:ơ!! )`),c(`%3±""5#7².6 &3³""5#7´.* &$;+0#*;+&/' 8!:Ʃ!! )`),c(`%;Ą/#2F""6F7G/x$;ă/o$2F""6F7G/\`$;ă/W$2F""6F7G/H$;ă/?$2F""6F7G/0$;ą/'$8):ƪ) )()'#(('#(''#(&'#(%'#($'#(#'#("'#&'#`),c(`%;#/>#;#/5$;#/,$;#/#$+$)($'#(#'#("'#&'#`),c(`%;ă/,#;ă/#$+")("'#&'#`),c(`%;ă/5#;ă/,$;ă/#$+#)(#'#("'#&'#`),c(`%;q/T#$;m0#*;m&/D$%; /,#;ø/#$+")("'#&'#." &"/#$+#)(#'#("'#&'#`),c(`%2ƫ""6ƫ7Ƭ.) &2ƭ""6ƭ7Ʈ/w#;0/n$;Ĉ/e$$%;B/2#;ĉ.# &; /#$+")("'#&'#0<*%;B/2#;ĉ.# &; /#$+")("'#&'#&/#$+$)($'#(#'#("'#&'#`),c(";.# &;L"),c(`%2Ư""6Ư7ư/5#;</,$;Ċ/#$+#)(#'#("'#&'#`),c(`%;D/S#;,/J$2:""6:7;/;$;,.# &;T/,$;E/#$+%)(%'#($'#(#'#("'#&'#`)];let d=0,f=0;const h=[{line:1,column:1}];let w=0,S=[],x=0,I;if(e.startRule!==void 0){if(!(e.startRule in s))throw new Error(`Can't start parsing from rule "`+e.startRule+'".');r=s[e.startRule]}function E(){return o.substring(f,d)}function ge(){return et(f,d)}function p(l,y){return{type:"literal",text:l,ignoreCase:y}}function $(l,y,u){return{type:"class",parts:l,inverted:y,ignoreCase:u}}function Qe(){return{type:"end"}}function xt(l){let y=h[l],u;if(y)return y;for(u=l-1;!h[u];)u--;for(y=h[u],y={line:y.line,column:y.column};u<l;)o.charCodeAt(u)===10?(y.line++,y.column=1):y.column++,u++;return h[l]=y,y}function et(l,y){const u=xt(l),G=xt(y);return{source:i,start:{offset:l,line:u.line,column:u.column},end:{offset:y,line:G.line,column:G.column}}}function It(l){d<w||(d>w&&(w=d,S=[]),S.push(l))}function Li(l,y,u){return new fe(fe.buildMessage(l,y),l,y,u)}function c(l){return l.split("").map(y=>y.charCodeAt(0)-32)}function At(l){const y=a[l];let u=0;const G=[];let D=y.length;const Q=[],C=[];let $t;for(;;){for(;u<D;)switch(y[u]){case 0:C.push(n[y[u+1]]),u+=2;break;case 1:C.push(void 0),u++;break;case 2:C.push(null),u++;break;case 3:C.push(t),u++;break;case 4:C.push([]),u++;break;case 5:C.push(d),u++;break;case 6:C.pop(),u++;break;case 7:d=C.pop(),u++;break;case 8:C.length-=y[u+1],u+=2;break;case 9:C.splice(-2,1),u++;break;case 10:C[C.length-2].push(C.pop()),u++;break;case 11:C.push(C.splice(C.length-y[u+1],y[u+1])),u+=2;break;case 12:C.push(o.substring(C.pop(),d)),u++;break;case 13:Q.push(D),G.push(u+3+y[u+1]+y[u+2]),C[C.length-1]?(D=u+3+y[u+1],u+=3):(D=u+3+y[u+1]+y[u+2],u+=3+y[u+1]);break;case 14:Q.push(D),G.push(u+3+y[u+1]+y[u+2]),C[C.length-1]===t?(D=u+3+y[u+1],u+=3):(D=u+3+y[u+1]+y[u+2],u+=3+y[u+1]);break;case 15:Q.push(D),G.push(u+3+y[u+1]+y[u+2]),C[C.length-1]!==t?(D=u+3+y[u+1],u+=3):(D=u+3+y[u+1]+y[u+2],u+=3+y[u+1]);break;case 16:C[C.length-1]!==t?(Q.push(D),G.push(u),D=u+2+y[u+1],u+=2):u+=2+y[u+1];break;case 17:Q.push(D),G.push(u+3+y[u+1]+y[u+2]),o.length>d?(D=u+3+y[u+1],u+=3):(D=u+3+y[u+1]+y[u+2],u+=3+y[u+1]);break;case 18:Q.push(D),G.push(u+4+y[u+2]+y[u+3]),o.substr(d,n[y[u+1]].length)===n[y[u+1]]?(D=u+4+y[u+2],u+=4):(D=u+4+y[u+2]+y[u+3],u+=4+y[u+2]);break;case 19:Q.push(D),G.push(u+4+y[u+2]+y[u+3]),o.substr(d,n[y[u+1]].length).toLowerCase()===n[y[u+1]]?(D=u+4+y[u+2],u+=4):(D=u+4+y[u+2]+y[u+3],u+=4+y[u+2]);break;case 20:Q.push(D),G.push(u+4+y[u+2]+y[u+3]),n[y[u+1]].test(o.charAt(d))?(D=u+4+y[u+2],u+=4):(D=u+4+y[u+2]+y[u+3],u+=4+y[u+2]);break;case 21:C.push(o.substr(d,y[u+1])),d+=y[u+1],u+=2;break;case 22:C.push(n[y[u+1]]),d+=n[y[u+1]].length,u+=2;break;case 23:C.push(t),x===0&&It(n[y[u+1]]),u+=2;break;case 24:f=C[C.length-1-y[u+1]],u+=2;break;case 25:f=d,u++;break;case 26:$t=y.slice(u+4,u+4+y[u+3]).map(function(ji){return C[C.length-1-ji]}),C.splice(C.length-y[u+2],y[u+2],n[y[u+1]].apply(null,$t)),u+=4+y[u+3];break;case 27:C.push(At(y[u+1])),u+=2;break;case 28:x++,u++;break;case 29:x--,u++;break;default:throw new Error("Invalid opcode: "+y[u]+".")}if(Q.length>0)D=Q.pop(),u=G.pop();else break}return C[0]}e.data={};function Bi(l,y){return[l].concat(y)}if(I=At(r),I!==t&&d===o.length)return I;throw I!==t&&d<o.length&&It(Qe()),Li(S,w<o.length?o.charAt(w):null,w<o.length?et(w,w+1):et(w,w))}const Ft=Ot;var k;(function(o){function e(s,r){const n={startRule:r};try{Ft(s,n)}catch{n.data=-1}return n.data}o.parse=e;function t(s){const r=o.parse(s,"Name_Addr_Header");return r!==-1?r:void 0}o.nameAddrHeaderParse=t;function i(s){const r=o.parse(s,"SIP_URI");return r!==-1?r:void 0}o.URIParse=i})(k=k||(k={}));const Nt={100:"Trying",180:"Ringing",181:"Call Is Being Forwarded",182:"Queued",183:"Session Progress",199:"Early Dialog Terminated",200:"OK",202:"Accepted",204:"No Notification",300:"Multiple Choices",301:"Moved Permanently",302:"Moved Temporarily",305:"Use Proxy",380:"Alternative Service",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",410:"Gone",412:"Conditional Request Failed",413:"Request Entity Too Large",414:"Request-URI Too Long",415:"Unsupported Media Type",416:"Unsupported URI Scheme",417:"Unknown Resource-Priority",420:"Bad Extension",421:"Extension Required",422:"Session Interval Too Small",423:"Interval Too Brief",428:"Use Identity Header",429:"Provide Referrer Identity",430:"Flow Failed",433:"Anonymity Disallowed",436:"Bad Identity-Info",437:"Unsupported Certificate",438:"Invalid Identity Header",439:"First Hop Lacks Outbound Support",440:"Max-Breadth Exceeded",469:"Bad Info Package",470:"Consent Needed",478:"Unresolvable Destination",480:"Temporarily Unavailable",481:"Call/Transaction Does Not Exist",482:"Loop Detected",483:"Too Many Hops",484:"Address Incomplete",485:"Ambiguous",486:"Busy Here",487:"Request Terminated",488:"Not Acceptable Here",489:"Bad Event",491:"Request Pending",493:"Undecipherable",494:"Security Agreement Required",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Server Time-out",505:"Version Not Supported",513:"Message Too Large",580:"Precondition Failure",600:"Busy Everywhere",603:"Decline",604:"Does Not Exist Anywhere",606:"Not Acceptable"};function le(o,e=32){let t="";for(let i=0;i<o;i++){const s=Math.floor(Math.random()*e);t+=s.toString(e)}return t}function Ie(o){return Nt[o]||""}function Ae(){return le(10)}function Y(o){const e={"Call-Id":"Call-ID",Cseq:"CSeq","Min-Se":"Min-SE",Rack:"RAck",Rseq:"RSeq","Www-Authenticate":"WWW-Authenticate"},t=o.toLowerCase().replace(/_/g,"-").split("-"),i=t.length;let s="";for(let r=0;r<i;r++)r!==0&&(s+="-"),s+=t[r].charAt(0).toUpperCase()+t[r].substring(1);return e[s]&&(s=e[s]),s}function Te(o){return encodeURIComponent(o).replace(/%[A-F\d]{2}/g,"U").length}class st{constructor(){this.headers={}}addHeader(e,t){const i={raw:t};e=Y(e),this.headers[e]?this.headers[e].push(i):this.headers[e]=[i]}getHeader(e){const t=this.headers[Y(e)];if(t){if(t[0])return t[0].raw}else return}getHeaders(e){const t=this.headers[Y(e)],i=[];if(!t)return[];for(const s of t)i.push(s.raw);return i}hasHeader(e){return!!this.headers[Y(e)]}parseHeader(e,t=0){if(e=Y(e),this.headers[e]){if(t>=this.headers[e].length)return}else return;const i=this.headers[e][t],s=i.raw;if(i.parsed)return i.parsed;const r=k.parse(s,e.replace(/-/g,"_"));if(r===-1){this.headers[e].splice(t,1);return}else return i.parsed=r,r}s(e,t=0){return this.parseHeader(e,t)}setHeader(e,t){this.headers[Y(e)]=[{raw:t}]}toString(){return this.data}}class pe extends st{constructor(){super()}}class se extends st{constructor(){super()}}class he{constructor(e,t,i,s,r,n,a){this.headers={},this.extraHeaders=[],this.options=he.getDefaultOptions(),r&&(this.options=Object.assign(Object.assign({},this.options),r),this.options.optionTags&&this.options.optionTags.length&&(this.options.optionTags=this.options.optionTags.slice()),this.options.routeSet&&this.options.routeSet.length&&(this.options.routeSet=this.options.routeSet.slice())),n&&n.length&&(this.extraHeaders=n.slice()),a&&(this.body={body:a.content,contentType:a.contentType}),this.method=e,this.ruri=t.clone(),this.fromURI=i.clone(),this.fromTag=this.options.fromTag?this.options.fromTag:Ae(),this.from=he.makeNameAddrHeader(this.fromURI,this.options.fromDisplayName,this.fromTag),this.toURI=s.clone(),this.toTag=this.options.toTag,this.to=he.makeNameAddrHeader(this.toURI,this.options.toDisplayName,this.toTag),this.callId=this.options.callId?this.options.callId:this.options.callIdPrefix+le(15),this.cseq=this.options.cseq,this.setHeader("route",this.options.routeSet),this.setHeader("via",""),this.setHeader("to",this.to.toString()),this.setHeader("from",this.from.toString()),this.setHeader("cseq",this.cseq+" "+this.method),this.setHeader("call-id",this.callId),this.setHeader("max-forwards","70")}static getDefaultOptions(){return{callId:"",callIdPrefix:"",cseq:1,toDisplayName:"",toTag:"",fromDisplayName:"",fromTag:"",forceRport:!1,hackViaTcp:!1,optionTags:["outbound"],routeSet:[],userAgentString:"sip.js",viaHost:""}}static makeNameAddrHeader(e,t,i){const s={};return i&&(s.tag=i),new N(e,t,s)}getHeader(e){const t=this.headers[Y(e)];if(t){if(t[0])return t[0]}else{const i=new RegExp("^\\s*"+e+"\\s*:","i");for(const s of this.extraHeaders)if(i.test(s))return s.substring(s.indexOf(":")+1).trim()}}getHeaders(e){const t=[],i=this.headers[Y(e)];if(i)for(const s of i)t.push(s);else{const s=new RegExp("^\\s*"+e+"\\s*:","i");for(const r of this.extraHeaders)s.test(r)&&t.push(r.substring(r.indexOf(":")+1).trim())}return t}hasHeader(e){if(this.headers[Y(e)])return!0;{const t=new RegExp("^\\s*"+e+"\\s*:","i");for(const i of this.extraHeaders)if(t.test(i))return!0}return!1}setHeader(e,t){this.headers[Y(e)]=t instanceof Array?t:[t]}setViaHeader(e,t){this.options.hackViaTcp&&(t="TCP");let i="SIP/2.0/"+t;i+=" "+this.options.viaHost+";branch="+e,this.options.forceRport&&(i+=";rport"),this.setHeader("via",i),this.branch=e}toString(){let e="";e+=this.method+" "+this.ruri.toRaw()+` SIP/2.0\r
|
|
8
|
+
`,!1),/^[0-9]/,$([["0","9"]],!1,!1),/^[a-zA-Z]/,$([["a","z"],["A","Z"]],!1,!1),/^[0-9a-fA-F]/,$([["0","9"],["a","f"],["A","F"]],!1,!1),/^[\0-\xFF]/,$([["\0","ÿ"]],!1,!1),/^["]/,$(['"'],!1,!1)," ",p(" ",!1)," ",p(" ",!1),/^[a-zA-Z0-9]/,$([["a","z"],["A","Z"],["0","9"]],!1,!1),";",p(";",!1),"/",p("/",!1),"?",p("?",!1),":",p(":",!1),"@",p("@",!1),"&",p("&",!1),"=",p("=",!1),"+",p("+",!1),"$",p("$",!1),",",p(",",!1),"-",p("-",!1),"_",p("_",!1),".",p(".",!1),"!",p("!",!1),"~",p("~",!1),"*",p("*",!1),"'",p("'",!1),"(",p("(",!1),")",p(")",!1),"%",p("%",!1),function(){return" "},function(){return":"},/^[!-~]/,$([["!","~"]],!1,!1),/^[\x80-\uFFFF]/,$([["",""]],!1,!1),/^[\x80-\xBF]/,$([["","¿"]],!1,!1),/^[a-f]/,$([["a","f"]],!1,!1),"`",p("`",!1),"<",p("<",!1),">",p(">",!1),"\\",p("\\",!1),"[",p("[",!1),"]",p("]",!1),"{",p("{",!1),"}",p("}",!1),function(){return"*"},function(){return"/"},function(){return"="},function(){return"("},function(){return")"},function(){return">"},function(){return"<"},function(){return","},function(){return";"},function(){return":"},function(){return'"'},/^[!-']/,$([["!","'"]],!1,!1),/^[*-[]/,$([["*","["]],!1,!1),/^[\]-~]/,$([["]","~"]],!1,!1),function(l){return l},/^[#-[]/,$([["#","["]],!1,!1),/^[\0-\t]/,$([["\0"," "]],!1,!1),/^[\v-\f]/,$([["\v","\f"]],!1,!1),/^[\x0E-\x7F]/,$([["",""]],!1,!1),function(){e=e||{data:{}},e.data.uri=new z(e.data.scheme,e.data.user,e.data.host,e.data.port),delete e.data.scheme,delete e.data.user,delete e.data.host,delete e.data.host_type,delete e.data.port},function(){e=e||{data:{}},e.data.uri=new z(e.data.scheme,e.data.user,e.data.host,e.data.port,e.data.uri_params,e.data.uri_headers),delete e.data.scheme,delete e.data.user,delete e.data.host,delete e.data.host_type,delete e.data.port,delete e.data.uri_params,e.startRule==="SIP_URI"&&(e.data=e.data.uri)},"sips",p("sips",!0),"sip",p("sip",!0),function(l){e=e||{data:{}},e.data.scheme=l},function(){e=e||{data:{}},e.data.user=decodeURIComponent(C().slice(0,-1))},function(){e=e||{data:{}},e.data.password=C()},function(){return e=e||{data:{}},e.data.host=C(),e.data.host},function(){return e=e||{data:{}},e.data.host_type="domain",C()},/^[a-zA-Z0-9_\-]/,$([["a","z"],["A","Z"],["0","9"],"_","-"],!1,!1),/^[a-zA-Z0-9\-]/,$([["a","z"],["A","Z"],["0","9"],"-"],!1,!1),function(){return e=e||{data:{}},e.data.host_type="IPv6",C()},"::",p("::",!1),function(){return e=e||{data:{}},e.data.host_type="IPv6",C()},function(){return e=e||{data:{}},e.data.host_type="IPv4",C()},"25",p("25",!1),/^[0-5]/,$([["0","5"]],!1,!1),"2",p("2",!1),/^[0-4]/,$([["0","4"]],!1,!1),"1",p("1",!1),/^[1-9]/,$([["1","9"]],!1,!1),function(l){return e=e||{data:{}},l=parseInt(l.join("")),e.data.port=l,l},"transport=",p("transport=",!0),"udp",p("udp",!0),"tcp",p("tcp",!0),"sctp",p("sctp",!0),"tls",p("tls",!0),function(l){e=e||{data:{}},e.data.uri_params||(e.data.uri_params={}),e.data.uri_params.transport=l.toLowerCase()},"user=",p("user=",!0),"phone",p("phone",!0),"ip",p("ip",!0),function(l){e=e||{data:{}},e.data.uri_params||(e.data.uri_params={}),e.data.uri_params.user=l.toLowerCase()},"method=",p("method=",!0),function(l){e=e||{data:{}},e.data.uri_params||(e.data.uri_params={}),e.data.uri_params.method=l},"ttl=",p("ttl=",!0),function(l){e=e||{data:{}},e.data.params||(e.data.params={}),e.data.params.ttl=l},"maddr=",p("maddr=",!0),function(l){e=e||{data:{}},e.data.uri_params||(e.data.uri_params={}),e.data.uri_params.maddr=l},"lr",p("lr",!0),function(){e=e||{data:{}},e.data.uri_params||(e.data.uri_params={}),e.data.uri_params.lr=void 0},function(l,b){e=e||{data:{}},e.data.uri_params||(e.data.uri_params={}),b===null?b=void 0:b=b[1],e.data.uri_params[l.toLowerCase()]=b},function(l,b){l=l.join("").toLowerCase(),b=b.join(""),e=e||{data:{}},e.data.uri_headers||(e.data.uri_headers={}),e.data.uri_headers[l]?e.data.uri_headers[l].push(b):e.data.uri_headers[l]=[b]},function(){e=e||{data:{}},e.startRule==="Refer_To"&&(e.data.uri=new z(e.data.scheme,e.data.user,e.data.host,e.data.port,e.data.uri_params,e.data.uri_headers),delete e.data.scheme,delete e.data.user,delete e.data.host,delete e.data.host_type,delete e.data.port,delete e.data.uri_params)},"//",p("//",!1),function(){e=e||{data:{}},e.data.scheme=C()},p("SIP",!0),function(){e=e||{data:{}},e.data.sip_version=C()},"INVITE",p("INVITE",!1),"ACK",p("ACK",!1),"VXACH",p("VXACH",!1),"OPTIONS",p("OPTIONS",!1),"BYE",p("BYE",!1),"CANCEL",p("CANCEL",!1),"REGISTER",p("REGISTER",!1),"SUBSCRIBE",p("SUBSCRIBE",!1),"NOTIFY",p("NOTIFY",!1),"REFER",p("REFER",!1),"PUBLISH",p("PUBLISH",!1),function(){return e=e||{data:{}},e.data.method=C(),e.data.method},function(l){e=e||{data:{}},e.data.status_code=parseInt(l.join(""))},function(){e=e||{data:{}},e.data.reason_phrase=C()},function(){e=e||{data:{}},e.data=C()},function(){var l,b;for(e=e||{data:{}},b=e.data.multi_header.length,l=0;l<b;l++)if(e.data.multi_header[l].parsed===null){e.data=null;break}e.data!==null?e.data=e.data.multi_header:e.data=-1},function(){var l;e=e||{data:{}},e.data.multi_header||(e.data.multi_header=[]);try{l=new N(e.data.uri,e.data.displayName,e.data.params),delete e.data.uri,delete e.data.displayName,delete e.data.params}catch{l=null}e.data.multi_header.push({position:d,offset:Q().start.offset,parsed:l})},function(l){l=C().trim(),l[0]==='"'&&(l=l.substring(1,l.length-1)),e=e||{data:{}},e.data.displayName=l},"q",p("q",!0),function(l){e=e||{data:{}},e.data.params||(e.data.params={}),e.data.params.q=l},"expires",p("expires",!0),function(l){e=e||{data:{}},e.data.params||(e.data.params={}),e.data.params.expires=l},function(l){return parseInt(l.join(""))},"0",p("0",!1),function(){return parseFloat(C())},function(l,b){e=e||{data:{}},e.data.params||(e.data.params={}),b===null?b=void 0:b=b[1],e.data.params[l.toLowerCase()]=b},"render",p("render",!0),"session",p("session",!0),"icon",p("icon",!0),"alert",p("alert",!0),function(){e=e||{data:{}},e.startRule==="Content_Disposition"&&(e.data.type=C().toLowerCase())},"handling",p("handling",!0),"optional",p("optional",!0),"required",p("required",!0),function(l){e=e||{data:{}},e.data=parseInt(l.join(""))},function(){e=e||{data:{}},e.data=C()},"text",p("text",!0),"image",p("image",!0),"audio",p("audio",!0),"video",p("video",!0),"application",p("application",!0),"message",p("message",!0),"multipart",p("multipart",!0),"x-",p("x-",!0),function(l){e=e||{data:{}},e.data.value=parseInt(l.join(""))},function(l){e=e||{data:{}},e.data=l},function(l){e=e||{data:{}},e.data.event=l.toLowerCase()},function(){e=e||{data:{}};var l=e.data.tag;e.data=new N(e.data.uri,e.data.displayName,e.data.params),l&&e.data.setParam("tag",l)},"tag",p("tag",!0),function(l){e=e||{data:{}},e.data.tag=l},function(l){e=e||{data:{}},e.data=parseInt(l.join(""))},function(l){e=e||{data:{}},e.data=l},function(){e=e||{data:{}},e.data=new N(e.data.uri,e.data.displayName,e.data.params)},"digest",p("Digest",!0),"realm",p("realm",!0),function(l){e=e||{data:{}},e.data.realm=l},"domain",p("domain",!0),"nonce",p("nonce",!0),function(l){e=e||{data:{}},e.data.nonce=l},"opaque",p("opaque",!0),function(l){e=e||{data:{}},e.data.opaque=l},"stale",p("stale",!0),"true",p("true",!0),function(){e=e||{data:{}},e.data.stale=!0},"false",p("false",!0),function(){e=e||{data:{}},e.data.stale=!1},"algorithm",p("algorithm",!0),"md5",p("MD5",!0),"md5-sess",p("MD5-sess",!0),function(l){e=e||{data:{}},e.data.algorithm=l.toUpperCase()},"qop",p("qop",!0),"auth-int",p("auth-int",!0),"auth",p("auth",!0),function(l){e=e||{data:{}},e.data.qop||(e.data.qop=[]),e.data.qop.push(l.toLowerCase())},function(l){e=e||{data:{}},e.data.value=parseInt(l.join(""))},function(){var l,b;for(e=e||{data:{}},b=e.data.multi_header.length,l=0;l<b;l++)if(e.data.multi_header[l].parsed===null){e.data=null;break}e.data!==null?e.data=e.data.multi_header:e.data=-1},function(){var l;e=e||{data:{}},e.data.multi_header||(e.data.multi_header=[]);try{l=new N(e.data.uri,e.data.displayName,e.data.params),delete e.data.uri,delete e.data.displayName,delete e.data.params}catch{l=null}e.data.multi_header.push({position:d,offset:Q().start.offset,parsed:l})},function(){e=e||{data:{}},e.data=new N(e.data.uri,e.data.displayName,e.data.params)},function(){e=e||{data:{}},e.data.replaces_from_tag&&e.data.replaces_to_tag||(e.data=-1)},function(){e=e||{data:{}},e.data={call_id:e.data}},"from-tag",p("from-tag",!0),function(l){e=e||{data:{}},e.data.replaces_from_tag=l},"to-tag",p("to-tag",!0),function(l){e=e||{data:{}},e.data.replaces_to_tag=l},"early-only",p("early-only",!0),function(){e=e||{data:{}},e.data.early_only=!0},function(l,b){return b},function(l,b){return zi(l,b)},function(l){e=e||{data:{}},e.startRule==="Require"&&(e.data=l||[])},function(l){e=e||{data:{}},e.data.value=parseInt(l.join(""))},"active",p("active",!0),"pending",p("pending",!0),"terminated",p("terminated",!0),function(){e=e||{data:{}},e.data.state=C()},"reason",p("reason",!0),function(l){e=e||{data:{}},typeof l<"u"&&(e.data.reason=l)},function(l){e=e||{data:{}},typeof l<"u"&&(e.data.expires=l)},"retry_after",p("retry_after",!0),function(l){e=e||{data:{}},typeof l<"u"&&(e.data.retry_after=l)},"deactivated",p("deactivated",!0),"probation",p("probation",!0),"rejected",p("rejected",!0),"timeout",p("timeout",!0),"giveup",p("giveup",!0),"noresource",p("noresource",!0),"invariant",p("invariant",!0),function(l){e=e||{data:{}},e.startRule==="Supported"&&(e.data=l||[])},function(){e=e||{data:{}};var l=e.data.tag;e.data=new N(e.data.uri,e.data.displayName,e.data.params),l&&e.data.setParam("tag",l)},"ttl",p("ttl",!0),function(l){e=e||{data:{}},e.data.ttl=l},"maddr",p("maddr",!0),function(l){e=e||{data:{}},e.data.maddr=l},"received",p("received",!0),function(l){e=e||{data:{}},e.data.received=l},"branch",p("branch",!0),function(l){e=e||{data:{}},e.data.branch=l},"rport",p("rport",!0),function(l){e=e||{data:{}},typeof l<"u"&&(e.data.rport=l.join(""))},function(l){e=e||{data:{}},e.data.protocol=l},p("UDP",!0),p("TCP",!0),p("TLS",!0),p("SCTP",!0),function(l){e=e||{data:{}},e.data.transport=l},function(){e=e||{data:{}},e.data.host=C()},function(l){e=e||{data:{}},e.data.port=parseInt(l.join(""))},function(l){return parseInt(l.join(""))},function(l){e=e||{data:{}},e.startRule==="Session_Expires"&&(e.data.deltaSeconds=l)},"refresher",p("refresher",!1),"uas",p("uas",!1),"uac",p("uac",!1),function(l){e=e||{data:{}},e.startRule==="Session_Expires"&&(e.data.refresher=l)},function(l){e=e||{data:{}},e.startRule==="Min_SE"&&(e.data=l)},"stuns",p("stuns",!0),"stun",p("stun",!0),function(l){e=e||{data:{}},e.data.scheme=l},function(l){e=e||{data:{}},e.data.host=l},"?transport=",p("?transport=",!1),"turns",p("turns",!0),"turn",p("turn",!0),function(l){e=e||{data:{}},e.data.transport=l},function(){e=e||{data:{}},e.data=C()},"Referred-By",p("Referred-By",!1),"b",p("b",!1),"cid",p("cid",!1)],o=[c('2 ""6 7!'),c('4"""5!7#'),c('4$""5!7%'),c(`4&""5!7'`),c(";'.# &;("),c('4(""5!7)'),c('4*""5!7+'),c('2,""6,7-'),c('2.""6.7/'),c('40""5!71'),c('22""6273. &24""6475.} &26""6677.q &28""6879.e &2:""6:7;.Y &2<""6<7=.M &2>""6>7?.A &2@""6@7A.5 &2B""6B7C.) &2D""6D7E'),c(";).# &;,"),c('2F""6F7G.} &2H""6H7I.q &2J""6J7K.e &2L""6L7M.Y &2N""6N7O.M &2P""6P7Q.A &2R""6R7S.5 &2T""6T7U.) &2V""6V7W'),c(`%%2X""6X7Y/5#;#/,$;#/#$+#)(#'#("'#&'#/"!&,)`),c(`%%$;$0#*;$&/,#; /#$+")("'#&'#." &"/=#$;$/�#*;$&&&#/'$8":Z" )("'#&'#`),c(';.." &"'),c(`%$;'.# &;(0)*;'.# &;(&/?#28""6879/0$;//'$8#:[# )(#'#("'#&'#`),c(`%%$;2/�#*;2&&&#/g#$%$;.0#*;.&/,#;2/#$+")("'#&'#0=*%$;.0#*;.&/,#;2/#$+")("'#&'#&/#$+")("'#&'#/"!&,)`),c('4\\""5!7].# &;3'),c('4^""5!7_'),c('4`""5!7a'),c(';!.) &4b""5!7c'),c('%$;). &2F""6F7G. &2J""6J7K.} &2L""6L7M.q &2X""6X7Y.e &2P""6P7Q.Y &2H""6H7I.M &2@""6@7A.A &2d""6d7e.5 &2R""6R7S.) &2N""6N7O/#0*;). &2F""6F7G. &2J""6J7K.} &2L""6L7M.q &2X""6X7Y.e &2P""6P7Q.Y &2H""6H7I.M &2@""6@7A.A &2d""6d7e.5 &2R""6R7S.) &2N""6N7O&&&#/"!&,)'),c('%$;). &2F""6F7G.} &2L""6L7M.q &2X""6X7Y.e &2P""6P7Q.Y &2H""6H7I.M &2@""6@7A.A &2d""6d7e.5 &2R""6R7S.) &2N""6N7O/#0*;). &2F""6F7G.} &2L""6L7M.q &2X""6X7Y.e &2P""6P7Q.Y &2H""6H7I.M &2@""6@7A.A &2d""6d7e.5 &2R""6R7S.) &2N""6N7O&&&#/"!&,)'),c(`2T""6T7U.ã &2V""6V7W.× &2f""6f7g.Ë &2h""6h7i.¿ &2:""6:7;.³ &2D""6D7E.§ &22""6273. &28""6879. &2j""6j7k. &;&.} &24""6475.q &2l""6l7m.e &2n""6n7o.Y &26""6677.M &2>""6>7?.A &2p""6p7q.5 &2r""6r7s.) &;'.# &;(`),c('%$;).ī &2F""6F7G.ğ &2J""6J7K.ē &2L""6L7M.ć &2X""6X7Y.û &2P""6P7Q.ï &2H""6H7I.ã &2@""6@7A.× &2d""6d7e.Ë &2R""6R7S.¿ &2N""6N7O.³ &2T""6T7U.§ &2V""6V7W. &2f""6f7g. &2h""6h7i. &28""6879.w &2j""6j7k.k &;&.e &24""6475.Y &2l""6l7m.M &2n""6n7o.A &26""6677.5 &2p""6p7q.) &2r""6r7s/Ĵ#0ı*;).ī &2F""6F7G.ğ &2J""6J7K.ē &2L""6L7M.ć &2X""6X7Y.û &2P""6P7Q.ï &2H""6H7I.ã &2@""6@7A.× &2d""6d7e.Ë &2R""6R7S.¿ &2N""6N7O.³ &2T""6T7U.§ &2V""6V7W. &2f""6f7g. &2h""6h7i. &28""6879.w &2j""6j7k.k &;&.e &24""6475.Y &2l""6l7m.M &2n""6n7o.A &26""6677.5 &2p""6p7q.) &2r""6r7s&&&#/"!&,)'),c(`%;//?#2P""6P7Q/0$;//'$8#:t# )(#'#("'#&'#`),c(`%;//?#24""6475/0$;//'$8#:u# )(#'#("'#&'#`),c(`%;//?#2>""6>7?/0$;//'$8#:v# )(#'#("'#&'#`),c(`%;//?#2T""6T7U/0$;//'$8#:w# )(#'#("'#&'#`),c(`%;//?#2V""6V7W/0$;//'$8#:x# )(#'#("'#&'#`),c(`%2h""6h7i/0#;//'$8":y" )("'#&'#`),c(`%;//6#2f""6f7g/'$8":z" )("'#&'#`),c(`%;//?#2D""6D7E/0$;//'$8#:{# )(#'#("'#&'#`),c(`%;//?#22""6273/0$;//'$8#:|# )(#'#("'#&'#`),c(`%;//?#28""6879/0$;//'$8#:}# )(#'#("'#&'#`),c(`%;//0#;&/'$8":~" )("'#&'#`),c(`%;&/0#;//'$8":~" )("'#&'#`),c(`%;=/T#$;G.) &;K.# &;F0/*;G.) &;K.# &;F&/,$;>/#$+#)(#'#("'#&'#`),c('4""5!7.A &4""5!7.5 &4""5!7.) &;3.# &;.'),c(`%%;//Q#;&/H$$;J.# &;K0)*;J.# &;K&/,$;&/#$+$)($'#(#'#("'#&'#/"!&,)`),c(`%;//]#;&/T$%$;J.# &;K0)*;J.# &;K&/"!&,)/1$;&/($8$:
$!!)($'#(#'#("'#&'#`),c(';..G &2L""6L7M.; &4""5!7./ &4""5!7.# &;3'),c(`%2j""6j7k/J#4""5!7.5 &4""5!7.) &4""5!7/#$+")("'#&'#`),c(`%;N/M#28""6879/>$;O." &"/0$;S/'$8$:$ )($'#(#'#("'#&'#`),c(`%;N/d#28""6879/U$;O." &"/G$;S/>$;_/5$;l." &"/'$8&:& )(&'#(%'#($'#(#'#("'#&'#`),c(`%3""5$7.) &3""5#7/' 8!:!! )`),c(`%;P/]#%28""6879/,#;R/#$+")("'#&'#." &"/6$2:""6:7;/'$8#:# )(#'#("'#&'#`),c("$;+.) &;-.# &;Q/2#0/*;+.) &;-.# &;Q&&&#"),c('2<""6<7=.q &2>""6>7?.e &2@""6@7A.Y &2B""6B7C.M &2D""6D7E.A &22""6273.5 &26""6677.) &24""6475'),c('%$;+._ &;-.Y &2<""6<7=.M &2>""6>7?.A &2@""6@7A.5 &2B""6B7C.) &2D""6D7E0e*;+._ &;-.Y &2<""6<7=.M &2>""6>7?.A &2@""6@7A.5 &2B""6B7C.) &2D""6D7E&/& 8!:! )'),c(`%;T/J#%28""6879/,#;^/#$+")("'#&'#." &"/#$+")("'#&'#`),c("%;U.) &;\\.# &;X/& 8!:! )"),c(`%$%;V/2#2J""6J7K/#$+")("'#&'#0<*%;V/2#2J""6J7K/#$+")("'#&'#&/D#;W/;$2J""6J7K." &"/'$8#:# )(#'#("'#&'#`),c('$4""5!7/,#0)*4""5!7&&&#'),c(`%4$""5!7%/?#$4""5!70)*4""5!7&/#$+")("'#&'#`),c(`%2l""6l7m/?#;Y/6$2n""6n7o/'$8#:# )(#'#("'#&'#`),c(`%%;Z/³#28""6879/¤$;Z/$28""6879/$;Z/$28""6879/t$;Z/k$28""6879/\\$;Z/S$28""6879/D$;Z/;$28""6879/,$;[/#$+-)(-'#(,'#(+'#(*'#()'#(('#(''#(&'#(%'#($'#(#'#("'#&'#.ސ &%2""67/¤#;Z/$28""6879/$;Z/$28""6879/t$;Z/k$28""6879/\\$;Z/S$28""6879/D$;Z/;$28""6879/,$;[/#$+,)(,'#(+'#(*'#()'#(('#(''#(&'#(%'#($'#(#'#("'#&'#.۹ &%2""67/#;Z/$28""6879/t$;Z/k$28""6879/\\$;Z/S$28""6879/D$;Z/;$28""6879/,$;[/#$+*)(*'#()'#(('#(''#(&'#(%'#($'#(#'#("'#&'#.ٺ &%2""67/t#;Z/k$28""6879/\\$;Z/S$28""6879/D$;Z/;$28""6879/,$;[/#$+()(('#(''#(&'#(%'#($'#(#'#("'#&'#.ؓ &%2""67/\\#;Z/S$28""6879/D$;Z/;$28""6879/,$;[/#$+&)(&'#(%'#($'#(#'#("'#&'#.ׄ &%2""67/D#;Z/;$28""6879/,$;[/#$+$)($'#(#'#("'#&'#.֍ &%2""67/,#;[/#$+")("'#&'#.ծ &%2""67/,#;Z/#$+")("'#&'#.Տ &%;Z/#2""67/$;Z/$28""6879/t$;Z/k$28""6879/\\$;Z/S$28""6879/D$;Z/;$28""6879/,$;[/#$++)(+'#(*'#()'#(('#(''#(&'#(%'#($'#(#'#("'#&'#.Ӈ &%;Z/ª#%28""6879/,#;Z/#$+")("'#&'#." &"/$2""67/t$;Z/k$28""6879/\\$;Z/S$28""6879/D$;Z/;$28""6879/,$;[/#$+*)(*'#()'#(('#(''#(&'#(%'#($'#(#'#("'#&'#.а &%;Z/¹#%28""6879/,#;Z/#$+")("'#&'#." &"/$%28""6879/,#;Z/#$+")("'#&'#." &"/k$2""67/\\$;Z/S$28""6879/D$;Z/;$28""6879/,$;[/#$+))()'#(('#(''#(&'#(%'#($'#(#'#("'#&'#.Ί &%;Z/È#%28""6879/,#;Z/#$+")("'#&'#." &"/¡$%28""6879/,#;Z/#$+")("'#&'#." &"/z$%28""6879/,#;Z/#$+")("'#&'#." &"/S$2""67/D$;Z/;$28""6879/,$;[/#$+()(('#(''#(&'#(%'#($'#(#'#("'#&'#.˕ &%;Z/×#%28""6879/,#;Z/#$+")("'#&'#." &"/°$%28""6879/,#;Z/#$+")("'#&'#." &"/$%28""6879/,#;Z/#$+")("'#&'#." &"/b$%28""6879/,#;Z/#$+")("'#&'#." &"/;$2""67/,$;[/#$+')(''#(&'#(%'#($'#(#'#("'#&'#.ȑ &%;Z/þ#%28""6879/,#;Z/#$+")("'#&'#." &"/×$%28""6879/,#;Z/#$+")("'#&'#." &"/°$%28""6879/,#;Z/#$+")("'#&'#." &"/$%28""6879/,#;Z/#$+")("'#&'#." &"/b$%28""6879/,#;Z/#$+")("'#&'#." &"/;$2""67/,$;Z/#$+()(('#(''#(&'#(%'#($'#(#'#("'#&'#.Ħ &%;Z/Ĝ#%28""6879/,#;Z/#$+")("'#&'#." &"/õ$%28""6879/,#;Z/#$+")("'#&'#." &"/Î$%28""6879/,#;Z/#$+")("'#&'#." &"/§$%28""6879/,#;Z/#$+")("'#&'#." &"/$%28""6879/,#;Z/#$+")("'#&'#." &"/Y$%28""6879/,#;Z/#$+")("'#&'#." &"/2$2""67/#$+()(('#(''#(&'#(%'#($'#(#'#("'#&'#/& 8!: ! )`),c(`%;#/M#;#." &"/?$;#." &"/1$;#." &"/#$+$)($'#(#'#("'#&'#`),c(`%;Z/;#28""6879/,$;Z/#$+#)(#'#("'#&'#.# &;\\`),c(`%;]/o#2J""6J7K/\`$;]/W$2J""6J7K/H$;]/?$2J""6J7K/0$;]/'$8':¡' )(''#(&'#(%'#($'#(#'#("'#&'#`),c(`%2¢""6¢7£/2#4¤""5!7¥/#$+")("'#&'#. &%2¦""6¦7§/;#4¨""5!7©/,$;!/#$+#)(#'#("'#&'#.j &%2ª""6ª7«/5#;!/,$;!/#$+#)(#'#("'#&'#.B &%4¬""5!7/,#;!/#$+")("'#&'#.# &;!`),c(`%%;!." &"/[#;!." &"/M$;!." &"/?$;!." &"/1$;!." &"/#$+%)(%'#($'#(#'#("'#&'#/' 8!:®!! )`),c(`$%22""6273/,#;\`/#$+")("'#&'#0<*%22""6273/,#;\`/#$+")("'#&'#&`),c(";a.A &;b.; &;c.5 &;d./ &;e.) &;f.# &;g"),c(`%3¯""5*7°/a#3±""5#7².G &3³""5#7´.; &3µ""5$7¶./ &3·""5#7¸.# &;6/($8":¹"! )("'#&'#`),c(`%3º""5%7»/I#3¼""5%7½./ &3¾""5"7¿.# &;6/($8":À"! )("'#&'#`),c(`%3Á""5'7Â/1#;/($8":Ã"! )("'#&'#`),c(`%3Ä""5$7Å/1#;ð/($8":Æ"! )("'#&'#`),c(`%3Ç""5&7È/1#;T/($8":É"! )("'#&'#`),c(`%3Ê""5"7Ë/N#%2>""6>7?/,#;6/#$+")("'#&'#." &"/'$8":Ì" )("'#&'#`),c(`%;h/P#%2>""6>7?/,#;i/#$+")("'#&'#." &"/)$8":Í""! )("'#&'#`),c('%$;j/�#*;j&&&#/"!&,)'),c('%$;j/�#*;j&&&#/"!&,)'),c(";k.) &;+.# &;-"),c('2l""6l7m.e &2n""6n7o.Y &24""6475.M &28""6879.A &2<""6<7=.5 &2@""6@7A.) &2B""6B7C'),c(`%26""6677/n#;m/e$$%2<""6<7=/,#;m/#$+")("'#&'#0<*%2<""6<7=/,#;m/#$+")("'#&'#&/#$+#)(#'#("'#&'#`),c(`%;n/A#2>""6>7?/2$;o/)$8#:Î#"" )(#'#("'#&'#`),c("$;p.) &;+.# &;-/2#0/*;p.) &;+.# &;-&&&#"),c("$;p.) &;+.# &;-0/*;p.) &;+.# &;-&"),c('2l""6l7m.e &2n""6n7o.Y &24""6475.M &26""6677.A &28""6879.5 &2@""6@7A.) &2B""6B7C'),c(";.# &;r"),c(`%;/G#;'/>$;s/5$;'/,$;/#$+%)(%'#($'#(#'#("'#&'#`),c(";M.# &;t"),c(`%;/E#28""6879/6$;u.# &;x/'$8#:Ï# )(#'#("'#&'#`),c(`%;v.# &;w/J#%26""6677/,#;/#$+")("'#&'#." &"/#$+")("'#&'#`),c(`%2Ð""6Ð7Ñ/:#;/1$;w." &"/#$+#)(#'#("'#&'#`),c(`%24""6475/,#;{/#$+")("'#&'#`),c(`%;z/3#$;y0#*;y&/#$+")("'#&'#`),c(";*.) &;+.# &;-"),c(';+. &;-. &22""6273.} &26""6677.q &28""6879.e &2:""6:7;.Y &2<""6<7=.M &2>""6>7?.A &2@""6@7A.5 &2B""6B7C.) &2D""6D7E'),c(`%;|/e#$%24""6475/,#;|/#$+")("'#&'#0<*%24""6475/,#;|/#$+")("'#&'#&/#$+")("'#&'#`),c(`%$;~0#*;~&/e#$%22""6273/,#;}/#$+")("'#&'#0<*%22""6273/,#;}/#$+")("'#&'#&/#$+")("'#&'#`),c("$;~0#*;~&"),c(';+.w &;-.q &28""6879.e &2:""6:7;.Y &2<""6<7=.M &2>""6>7?.A &2@""6@7A.5 &2B""6B7C.) &2D""6D7E'),c(`%%;"/#$;".G &;!.A &2@""6@7A.5 &2F""6F7G.) &2J""6J7K0M*;".G &;!.A &2@""6@7A.5 &2F""6F7G.) &2J""6J7K&/#$+")("'#&'#/& 8!:Ò! )`),c(";.# &;"),c(`%%;O/2#2:""6:7;/#$+")("'#&'#." &"/,#;S/#$+")("'#&'#." &"`),c('$;+. &;-.} &2B""6B7C.q &2D""6D7E.e &22""6273.Y &28""6879.M &2:""6:7;.A &2<""6<7=.5 &2>""6>7?.) &2@""6@7A/#0*;+. &;-.} &2B""6B7C.q &2D""6D7E.e &22""6273.Y &28""6879.M &2:""6:7;.A &2<""6<7=.5 &2>""6>7?.) &2@""6@7A&&&#'),c("$;y0#*;y&"),c(`%3""5#7Ó/q#24""6475/b$$;!/�#*;!&&&#/L$2J""6J7K/=$$;!/�#*;!&&&#/'$8%:Ô% )(%'#($'#(#'#("'#&'#`),c('2Õ""6Õ7Ö'),c('2×""6×7Ø'),c('2Ù""6Ù7Ú'),c('2Û""6Û7Ü'),c('2Ý""6Ý7Þ'),c('2ß""6ß7à'),c('2á""6á7â'),c('2ã""6ã7ä'),c('2å""6å7æ'),c('2ç""6ç7è'),c('2é""6é7ê'),c("%;
.Y &;.S &;.M &;.G &;.A &;.; &;.5 &;./ &;.) &;.# &;6/& 8!:ë! )"),c(`%;/G#;'/>$;/5$;'/,$;/#$+%)(%'#($'#(#'#("'#&'#`),c("%;/' 8!:ì!! )"),c(`%;!/5#;!/,$;!/#$+#)(#'#("'#&'#`),c("%$;*.A &;+.; &;-.5 &;3./ &;4.) &;'.# &;(0G*;*.A &;+.; &;-.5 &;3./ &;4.) &;'.# &;(&/& 8!:í! )"),c(`%;¶/Y#$%;A/,#;¶/#$+")("'#&'#06*%;A/,#;¶/#$+")("'#&'#&/#$+")("'#&'#`),c(`%;9/N#%2:""6:7;/,#;9/#$+")("'#&'#." &"/'$8":î" )("'#&'#`),c(`%;:.c &%;/Y#$%;A/,#;/#$+")("'#&'#06*%;A/,#;/#$+")("'#&'#&/#$+")("'#&'#/& 8!:ï! )`),c(`%;L.# &;/]#$%;B/,#;/#$+")("'#&'#06*%;B/,#;/#$+")("'#&'#&/'$8":ð" )("'#&'#`),c(`%;." &"/>#;@/5$;M/,$;?/#$+$)($'#(#'#("'#&'#`),c(`%%;6/Y#$%;./,#;6/#$+")("'#&'#06*%;./,#;6/#$+")("'#&'#&/#$+")("'#&'#.# &;H/' 8!:ñ!! )`),c(";.) &;.# &; "),c(`%3ò""5!7ó/:#;</1$;/($8#:ô#! )(#'#("'#&'#`),c(`%3õ""5'7ö/:#;</1$;/($8#:÷#! )(#'#("'#&'#`),c("%$;!/�#*;!&&&#/' 8!:ø!! )"),c(`%2ù""6ù7ú/o#%2J""6J7K/M#;!." &"/?$;!." &"/1$;!." &"/#$+$)($'#(#'#("'#&'#." &"/'$8":û" )("'#&'#`),c(`%;6/J#%;</,#;¡/#$+")("'#&'#." &"/)$8":ü""! )("'#&'#`),c(";6.) &;T.# &;H"),c(`%;£/Y#$%;B/,#;¤/#$+")("'#&'#06*%;B/,#;¤/#$+")("'#&'#&/#$+")("'#&'#`),c(`%3ý""5&7þ.G &3ÿ""5'7Ā.; &3ā""5$7Ă./ &3ă""5%7Ą.# &;6/& 8!:ą! )`),c(";¥.# &; "),c(`%3Ć""5(7ć/M#;</D$3Ĉ""5(7ĉ./ &3Ċ""5(7ċ.# &;6/#$+#)(#'#("'#&'#`),c(`%;6/Y#$%;A/,#;6/#$+")("'#&'#06*%;A/,#;6/#$+")("'#&'#&/#$+")("'#&'#`),c("%$;!/�#*;!&&&#/' 8!:Č!! )"),c("%;©/& 8!:č! )"),c(`%;ª/k#;;/b$;¯/Y$$%;B/,#;°/#$+")("'#&'#06*%;B/,#;°/#$+")("'#&'#&/#$+$)($'#(#'#("'#&'#`),c(";«.# &;¬"),c('3Ď""5$7ď.S &3Đ""5%7đ.G &3Ē""5%7ē.; &3Ĕ""5%7ĕ./ &3Ė""5+7ė.# &;'),c(`3Ę""5'7ę./ &3Ě""5)7ě.# &;`),c(";6.# &;®"),c(`%3Ĝ""5"7ĝ/,#;6/#$+")("'#&'#`),c(";.# &;6"),c(`%;6/5#;</,$;±/#$+#)(#'#("'#&'#`),c(";6.# &;H"),c(`%;³/5#;./,$;/#$+#)(#'#("'#&'#`),c("%$;!/�#*;!&&&#/' 8!:Ğ!! )"),c("%;/' 8!:ğ!! )"),c(`%;¶/^#$%;B/,#; /#$+")("'#&'#06*%;B/,#; /#$+")("'#&'#&/($8":Ġ"!!)("'#&'#`),c(`%%;7/e#$%2J""6J7K/,#;7/#$+")("'#&'#0<*%2J""6J7K/,#;7/#$+")("'#&'#&/#$+")("'#&'#/"!&,)`),c(`%;L.# &;/]#$%;B/,#;¸/#$+")("'#&'#06*%;B/,#;¸/#$+")("'#&'#&/'$8":ġ" )("'#&'#`),c(";¹.# &; "),c(`%3Ģ""5#7ģ/:#;</1$;6/($8#:Ĥ#! )(#'#("'#&'#`),c("%$;!/�#*;!&&&#/' 8!:ĥ!! )"),c("%;/' 8!:Ħ!! )"),c(`%$;0#*;&/x#;@/o$;M/f$;?/]$$%;B/,#; /#$+")("'#&'#06*%;B/,#; /#$+")("'#&'#&/'$8%:ħ% )(%'#($'#(#'#("'#&'#`),c(";¾"),c(`%3Ĩ""5&7ĩ/k#;./b$;Á/Y$$%;A/,#;Á/#$+")("'#&'#06*%;A/,#;Á/#$+")("'#&'#&/#$+$)($'#(#'#("'#&'#.# &;¿`),c(`%;6/k#;./b$;À/Y$$%;A/,#;À/#$+")("'#&'#06*%;A/,#;À/#$+")("'#&'#&/#$+$)($'#(#'#("'#&'#`),c(`%;6/;#;</2$;6.# &;H/#$+#)(#'#("'#&'#`),c(";Â.G &;Ä.A &;Æ.; &;È.5 &;É./ &;Ê.) &;Ë.# &;À"),c(`%3Ī""5%7ī/5#;</,$;Ã/#$+#)(#'#("'#&'#`),c("%;I/' 8!:Ĭ!! )"),c(`%3ĭ""5&7Į/#;</$;D/
$;Å/|$$%$;'/�#*;'&&&#/,#;Å/#$+")("'#&'#0C*%$;'/�#*;'&&&#/,#;Å/#$+")("'#&'#&/,$;E/#$+&)(&'#(%'#($'#(#'#("'#&'#`),c(";t.# &;w"),c(`%3į""5%7İ/5#;</,$;Ç/#$+#)(#'#("'#&'#`),c("%;I/' 8!:ı!! )"),c(`%3IJ""5&7ij/:#;</1$;I/($8#:Ĵ#! )(#'#("'#&'#`),c(`%3ĵ""5%7Ķ/]#;</T$%3ķ""5$7ĸ/& 8!:Ĺ! ).4 &%3ĺ""5%7Ļ/& 8!:ļ! )/#$+#)(#'#("'#&'#`),c(`%3Ľ""5)7ľ/R#;</I$3Ŀ""5#7ŀ./ &3Ł""5(7ł.# &;6/($8#:Ń#! )(#'#("'#&'#`),c(`%3ń""5#7Ņ/#;</$;D/$%;Ì/e#$%2D""6D7E/,#;Ì/#$+")("'#&'#0<*%2D""6D7E/,#;Ì/#$+")("'#&'#&/#$+")("'#&'#/,$;E/#$+%)(%'#($'#(#'#("'#&'#`),c(`%3ņ""5(7Ň./ &3ň""5$7ʼn.# &;6/' 8!:Ŋ!! )`),c(`%;6/Y#$%;A/,#;6/#$+")("'#&'#06*%;A/,#;6/#$+")("'#&'#&/#$+")("'#&'#`),c(`%;Ï/G#;./>$;Ï/5$;./,$;/#$+%)(%'#($'#(#'#("'#&'#`),c("%$;!/�#*;!&&&#/' 8!:ŋ!! )"),c(`%;Ñ/]#$%;A/,#;Ñ/#$+")("'#&'#06*%;A/,#;Ñ/#$+")("'#&'#&/'$8":Ō" )("'#&'#`),c(`%;/]#$%;B/,#; /#$+")("'#&'#06*%;B/,#; /#$+")("'#&'#&/'$8":ō" )("'#&'#`),c(`%;L.O &;.I &%;@." &"/:#;t/1$;?." &"/#$+#)(#'#("'#&'#/]#$%;B/,#; /#$+")("'#&'#06*%;B/,#; /#$+")("'#&'#&/'$8":Ŏ" )("'#&'#`),c(`%;Ô/]#$%;B/,#;Õ/#$+")("'#&'#06*%;B/,#;Õ/#$+")("'#&'#&/'$8":ŏ" )("'#&'#`),c("%;/& 8!:Ő! )"),c(`%3ő""5(7Œ/:#;</1$;6/($8#:œ#! )(#'#("'#&'#.g &%3Ŕ""5&7ŕ/:#;</1$;6/($8#:Ŗ#! )(#'#("'#&'#.: &%3ŗ""5*7Ř/& 8!:ř! ).# &; `),c(`%%;6/k#$%;A/2#;6/)$8":Ś""$ )("'#&'#0<*%;A/2#;6/)$8":Ś""$ )("'#&'#&/)$8":ś""! )("'#&'#." &"/' 8!:Ŝ!! )`),c(`%;Ø/Y#$%;A/,#;Ø/#$+")("'#&'#06*%;A/,#;Ø/#$+")("'#&'#&/#$+")("'#&'#`),c(`%;/Y#$%;B/,#; /#$+")("'#&'#06*%;B/,#; /#$+")("'#&'#&/#$+")("'#&'#`),c("%$;!/�#*;!&&&#/' 8!:ŝ!! )"),c(`%;Û/Y#$%;B/,#;Ü/#$+")("'#&'#06*%;B/,#;Ü/#$+")("'#&'#&/#$+")("'#&'#`),c(`%3Ş""5&7ş.; &3Š""5'7š./ &3Ţ""5*7ţ.# &;6/& 8!:Ť! )`),c(`%3ť""5&7Ŧ/:#;</1$;Ý/($8#:ŧ#! )(#'#("'#&'#.} &%3õ""5'7ö/:#;</1$;/($8#:Ũ#! )(#'#("'#&'#.P &%3ũ""5+7Ū/:#;</1$;/($8#:ū#! )(#'#("'#&'#.# &; `),c(`3Ŭ""5+7ŭ.k &3Ů""5)7ů._ &3Ű""5(7ű.S &3Ų""5'7ų.G &3Ŵ""5&7ŵ.; &3Ŷ""5*7ŷ./ &3Ÿ""5)7Ź.# &;6`),c(';1." &"'),c(`%%;6/k#$%;A/2#;6/)$8":Ś""$ )("'#&'#0<*%;A/2#;6/)$8":Ś""$ )("'#&'#&/)$8":ś""! )("'#&'#." &"/' 8!:ź!! )`),c(`%;L.# &;/]#$%;B/,#;á/#$+")("'#&'#06*%;B/,#;á/#$+")("'#&'#&/'$8":Ż" )("'#&'#`),c(";¹.# &; "),c(`%;ã/Y#$%;A/,#;ã/#$+")("'#&'#06*%;A/,#;ã/#$+")("'#&'#&/#$+")("'#&'#`),c(`%;ê/k#;./b$;í/Y$$%;B/,#;ä/#$+")("'#&'#06*%;B/,#;ä/#$+")("'#&'#&/#$+$)($'#(#'#("'#&'#`),c(";å.; &;æ.5 &;ç./ &;è.) &;é.# &; "),c(`%3ż""5#7Ž/:#;</1$;ð/($8#:ž#! )(#'#("'#&'#`),c(`%3ſ""5%7ƀ/:#;</1$;T/($8#:Ɓ#! )(#'#("'#&'#`),c(`%3Ƃ""5(7ƃ/F#;</=$;\\.) &;Y.# &;X/($8#:Ƅ#! )(#'#("'#&'#`),c(`%3ƅ""5&7Ɔ/:#;</1$;6/($8#:Ƈ#! )(#'#("'#&'#`),c(`%3ƈ""5%7Ɖ/A#;</8$$;!0#*;!&/($8#:Ɗ#! )(#'#("'#&'#`),c(`%;ë/G#;;/>$;6/5$;;/,$;ì/#$+%)(%'#($'#(#'#("'#&'#`),c(`%3""5#7Ó.# &;6/' 8!:Ƌ!! )`),c(`%3±""5#7ƌ.G &3³""5#7ƍ.; &3·""5#7Ǝ./ &3µ""5$7Ə.# &;6/' 8!:Ɛ!! )`),c(`%;î/D#%;C/,#;ï/#$+")("'#&'#." &"/#$+")("'#&'#`),c("%;U.) &;\\.# &;X/& 8!:Ƒ! )"),c(`%%;!." &"/[#;!." &"/M$;!." &"/?$;!." &"/1$;!." &"/#$+%)(%'#($'#(#'#("'#&'#/' 8!:ƒ!! )`),c(`%%;!/?#;!." &"/1$;!." &"/#$+#)(#'#("'#&'#/' 8!:Ɠ!! )`),c(";¾"),c(`%;/^#$%;B/,#;ó/#$+")("'#&'#06*%;B/,#;ó/#$+")("'#&'#&/($8":Ɣ"!!)("'#&'#`),c(";ô.# &; "),c(`%2ƕ""6ƕ7Ɩ/L#;</C$2Ɨ""6Ɨ7Ƙ.) &2ƙ""6ƙ7ƚ/($8#:ƛ#! )(#'#("'#&'#`),c(`%;/^#$%;B/,#; /#$+")("'#&'#06*%;B/,#; /#$+")("'#&'#&/($8":Ɯ"!!)("'#&'#`),c(`%;6/5#;0/,$;÷/#$+#)(#'#("'#&'#`),c("$;2.) &;4.# &;.0/*;2.) &;4.# &;.&"),c("$;%0#*;%&"),c(`%;ú/;#28""6879/,$;û/#$+#)(#'#("'#&'#`),c(`%3Ɲ""5%7ƞ.) &3Ɵ""5$7Ơ/' 8!:ơ!! )`),c(`%;ü/J#%28""6879/,#;^/#$+")("'#&'#." &"/#$+")("'#&'#`),c("%;\\.) &;X.# &;/' 8!:Ƣ!! )"),c(';".S &;!.M &2F""6F7G.A &2J""6J7K.5 &2H""6H7I.) &2N""6N7O'),c('2L""6L7M. &2B""6B7C. &2<""6<7=.} &2R""6R7S.q &2T""6T7U.e &2V""6V7W.Y &2P""6P7Q.M &2@""6@7A.A &2D""6D7E.5 &22""6273.) &2>""6>7?'),c(`%;Ā/b#28""6879/S$;û/J$%2ƣ""6ƣ7Ƥ/,#;ì/#$+")("'#&'#." &"/#$+$)($'#(#'#("'#&'#`),c(`%3ƥ""5%7Ʀ.) &3Ƨ""5$7ƨ/' 8!:ơ!! )`),c(`%3±""5#7².6 &3³""5#7´.* &$;+0#*;+&/' 8!:Ʃ!! )`),c(`%;Ą/#2F""6F7G/x$;ă/o$2F""6F7G/\`$;ă/W$2F""6F7G/H$;ă/?$2F""6F7G/0$;ą/'$8):ƪ) )()'#(('#(''#(&'#(%'#($'#(#'#("'#&'#`),c(`%;#/>#;#/5$;#/,$;#/#$+$)($'#(#'#("'#&'#`),c(`%;ă/,#;ă/#$+")("'#&'#`),c(`%;ă/5#;ă/,$;ă/#$+#)(#'#("'#&'#`),c(`%;q/T#$;m0#*;m&/D$%; /,#;ø/#$+")("'#&'#." &"/#$+#)(#'#("'#&'#`),c(`%2ƫ""6ƫ7Ƭ.) &2ƭ""6ƭ7Ʈ/w#;0/n$;Ĉ/e$$%;B/2#;ĉ.# &; /#$+")("'#&'#0<*%;B/2#;ĉ.# &; /#$+")("'#&'#&/#$+$)($'#(#'#("'#&'#`),c(";.# &;L"),c(`%2Ư""6Ư7ư/5#;</,$;Ċ/#$+#)(#'#("'#&'#`),c(`%;D/S#;,/J$2:""6:7;/;$;,.# &;T/,$;E/#$+%)(%'#($'#(#'#("'#&'#`)];let d=0,u=0;const h=[{line:1,column:1}];let m=0,S=[],x=0,_;if(e.startRule!==void 0){if(!(e.startRule in s))throw new Error(`Can't start parsing from rule "`+e.startRule+'".');r=s[e.startRule]}function C(){return a.substring(u,d)}function Q(){return tt(u,d)}function p(l,b){return{type:"literal",text:l,ignoreCase:b}}function $(l,b,g){return{type:"class",parts:l,inverted:b,ignoreCase:g}}function et(){return{type:"end"}}function It(l){let b=h[l],g;if(b)return b;for(g=l-1;!h[g];)g--;for(b=h[g],b={line:b.line,column:b.column};g<l;)a.charCodeAt(g)===10?(b.line++,b.column=1):b.column++,g++;return h[l]=b,b}function tt(l,b){const g=It(l),G=It(b);return{source:i,start:{offset:l,line:g.line,column:g.column},end:{offset:b,line:G.line,column:G.column}}}function At(l){d<m||(d>m&&(m=d,S=[]),S.push(l))}function Ki(l,b,g){return new pe(pe.buildMessage(l,b),l,b,g)}function c(l){return l.split("").map(b=>b.charCodeAt(0)-32)}function $t(l){const b=o[l];let g=0;const G=[];let D=b.length;const ee=[],E=[];let Dt;for(;;){for(;g<D;)switch(b[g]){case 0:E.push(n[b[g+1]]),g+=2;break;case 1:E.push(void 0),g++;break;case 2:E.push(null),g++;break;case 3:E.push(t),g++;break;case 4:E.push([]),g++;break;case 5:E.push(d),g++;break;case 6:E.pop(),g++;break;case 7:d=E.pop(),g++;break;case 8:E.length-=b[g+1],g+=2;break;case 9:E.splice(-2,1),g++;break;case 10:E[E.length-2].push(E.pop()),g++;break;case 11:E.push(E.splice(E.length-b[g+1],b[g+1])),g+=2;break;case 12:E.push(a.substring(E.pop(),d)),g++;break;case 13:ee.push(D),G.push(g+3+b[g+1]+b[g+2]),E[E.length-1]?(D=g+3+b[g+1],g+=3):(D=g+3+b[g+1]+b[g+2],g+=3+b[g+1]);break;case 14:ee.push(D),G.push(g+3+b[g+1]+b[g+2]),E[E.length-1]===t?(D=g+3+b[g+1],g+=3):(D=g+3+b[g+1]+b[g+2],g+=3+b[g+1]);break;case 15:ee.push(D),G.push(g+3+b[g+1]+b[g+2]),E[E.length-1]!==t?(D=g+3+b[g+1],g+=3):(D=g+3+b[g+1]+b[g+2],g+=3+b[g+1]);break;case 16:E[E.length-1]!==t?(ee.push(D),G.push(g),D=g+2+b[g+1],g+=2):g+=2+b[g+1];break;case 17:ee.push(D),G.push(g+3+b[g+1]+b[g+2]),a.length>d?(D=g+3+b[g+1],g+=3):(D=g+3+b[g+1]+b[g+2],g+=3+b[g+1]);break;case 18:ee.push(D),G.push(g+4+b[g+2]+b[g+3]),a.substr(d,n[b[g+1]].length)===n[b[g+1]]?(D=g+4+b[g+2],g+=4):(D=g+4+b[g+2]+b[g+3],g+=4+b[g+2]);break;case 19:ee.push(D),G.push(g+4+b[g+2]+b[g+3]),a.substr(d,n[b[g+1]].length).toLowerCase()===n[b[g+1]]?(D=g+4+b[g+2],g+=4):(D=g+4+b[g+2]+b[g+3],g+=4+b[g+2]);break;case 20:ee.push(D),G.push(g+4+b[g+2]+b[g+3]),n[b[g+1]].test(a.charAt(d))?(D=g+4+b[g+2],g+=4):(D=g+4+b[g+2]+b[g+3],g+=4+b[g+2]);break;case 21:E.push(a.substr(d,b[g+1])),d+=b[g+1],g+=2;break;case 22:E.push(n[b[g+1]]),d+=n[b[g+1]].length,g+=2;break;case 23:E.push(t),x===0&&At(n[b[g+1]]),g+=2;break;case 24:u=E[E.length-1-b[g+1]],g+=2;break;case 25:u=d,g++;break;case 26:Dt=b.slice(g+4,g+4+b[g+3]).map(function(Yi){return E[E.length-1-Yi]}),E.splice(E.length-b[g+2],b[g+2],n[b[g+1]].apply(null,Dt)),g+=4+b[g+3];break;case 27:E.push($t(b[g+1])),g+=2;break;case 28:x++,g++;break;case 29:x--,g++;break;default:throw new Error("Invalid opcode: "+b[g]+".")}if(ee.length>0)D=ee.pop(),g=G.pop();else break}return E[0]}e.data={};function zi(l,b){return[l].concat(b)}if(_=$t(r),_!==t&&d===a.length)return _;throw _!==t&&d<a.length&&At(et()),Ki(S,m<a.length?a.charAt(m):null,m<a.length?tt(m,m+1):tt(m,m))}const Nt=Ft;var P;(function(a){function e(s,r){const n={startRule:r};try{Nt(s,n)}catch{n.data=-1}return n.data}a.parse=e;function t(s){const r=a.parse(s,"Name_Addr_Header");return r!==-1?r:void 0}a.nameAddrHeaderParse=t;function i(s){const r=a.parse(s,"SIP_URI");return r!==-1?r:void 0}a.URIParse=i})(P=P||(P={}));const Ut={100:"Trying",180:"Ringing",181:"Call Is Being Forwarded",182:"Queued",183:"Session Progress",199:"Early Dialog Terminated",200:"OK",202:"Accepted",204:"No Notification",300:"Multiple Choices",301:"Moved Permanently",302:"Moved Temporarily",305:"Use Proxy",380:"Alternative Service",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",410:"Gone",412:"Conditional Request Failed",413:"Request Entity Too Large",414:"Request-URI Too Long",415:"Unsupported Media Type",416:"Unsupported URI Scheme",417:"Unknown Resource-Priority",420:"Bad Extension",421:"Extension Required",422:"Session Interval Too Small",423:"Interval Too Brief",428:"Use Identity Header",429:"Provide Referrer Identity",430:"Flow Failed",433:"Anonymity Disallowed",436:"Bad Identity-Info",437:"Unsupported Certificate",438:"Invalid Identity Header",439:"First Hop Lacks Outbound Support",440:"Max-Breadth Exceeded",469:"Bad Info Package",470:"Consent Needed",478:"Unresolvable Destination",480:"Temporarily Unavailable",481:"Call/Transaction Does Not Exist",482:"Loop Detected",483:"Too Many Hops",484:"Address Incomplete",485:"Ambiguous",486:"Busy Here",487:"Request Terminated",488:"Not Acceptable Here",489:"Bad Event",491:"Request Pending",493:"Undecipherable",494:"Security Agreement Required",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Server Time-out",505:"Version Not Supported",513:"Message Too Large",580:"Precondition Failure",600:"Busy Everywhere",603:"Decline",604:"Does Not Exist Anywhere",606:"Not Acceptable"};function ue(a,e=32){let t="";for(let i=0;i<a;i++){const s=Math.floor(Math.random()*e);t+=s.toString(e)}return t}function Ae(a){return Ut[a]||""}function $e(){return ue(10)}function Y(a){const e={"Call-Id":"Call-ID",Cseq:"CSeq","Min-Se":"Min-SE",Rack:"RAck",Rseq:"RSeq","Www-Authenticate":"WWW-Authenticate"},t=a.toLowerCase().replace(/_/g,"-").split("-"),i=t.length;let s="";for(let r=0;r<i;r++)r!==0&&(s+="-"),s+=t[r].charAt(0).toUpperCase()+t[r].substring(1);return e[s]&&(s=e[s]),s}function Ce(a){return encodeURIComponent(a).replace(/%[A-F\d]{2}/g,"U").length}class rt{constructor(){this.headers={}}addHeader(e,t){const i={raw:t};e=Y(e),this.headers[e]?this.headers[e].push(i):this.headers[e]=[i]}getHeader(e){const t=this.headers[Y(e)];if(t){if(t[0])return t[0].raw}else return}getHeaders(e){const t=this.headers[Y(e)],i=[];if(!t)return[];for(const s of t)i.push(s.raw);return i}hasHeader(e){return!!this.headers[Y(e)]}parseHeader(e,t=0){if(e=Y(e),this.headers[e]){if(t>=this.headers[e].length)return}else return;const i=this.headers[e][t],s=i.raw;if(i.parsed)return i.parsed;const r=P.parse(s,e.replace(/-/g,"_"));if(r===-1){this.headers[e].splice(t,1);return}else return i.parsed=r,r}s(e,t=0){return this.parseHeader(e,t)}setHeader(e,t){this.headers[Y(e)]=[{raw:t}]}toString(){return this.data}}class me extends rt{constructor(){super()}}class re extends rt{constructor(){super()}}class ge{constructor(e,t,i,s,r,n,o){this.headers={},this.extraHeaders=[],this.options=ge.getDefaultOptions(),r&&(this.options=Object.assign(Object.assign({},this.options),r),this.options.optionTags&&this.options.optionTags.length&&(this.options.optionTags=this.options.optionTags.slice()),this.options.routeSet&&this.options.routeSet.length&&(this.options.routeSet=this.options.routeSet.slice())),n&&n.length&&(this.extraHeaders=n.slice()),o&&(this.body={body:o.content,contentType:o.contentType}),this.method=e,this.ruri=t.clone(),this.fromURI=i.clone(),this.fromTag=this.options.fromTag?this.options.fromTag:$e(),this.from=ge.makeNameAddrHeader(this.fromURI,this.options.fromDisplayName,this.fromTag),this.toURI=s.clone(),this.toTag=this.options.toTag,this.to=ge.makeNameAddrHeader(this.toURI,this.options.toDisplayName,this.toTag),this.callId=this.options.callId?this.options.callId:this.options.callIdPrefix+ue(15),this.cseq=this.options.cseq,this.setHeader("route",this.options.routeSet),this.setHeader("via",""),this.setHeader("to",this.to.toString()),this.setHeader("from",this.from.toString()),this.setHeader("cseq",this.cseq+" "+this.method),this.setHeader("call-id",this.callId),this.setHeader("max-forwards","70")}static getDefaultOptions(){return{callId:"",callIdPrefix:"",cseq:1,toDisplayName:"",toTag:"",fromDisplayName:"",fromTag:"",forceRport:!1,hackViaTcp:!1,optionTags:["outbound"],routeSet:[],userAgentString:"sip.js",viaHost:""}}static makeNameAddrHeader(e,t,i){const s={};return i&&(s.tag=i),new N(e,t,s)}getHeader(e){const t=this.headers[Y(e)];if(t){if(t[0])return t[0]}else{const i=new RegExp("^\\s*"+e+"\\s*:","i");for(const s of this.extraHeaders)if(i.test(s))return s.substring(s.indexOf(":")+1).trim()}}getHeaders(e){const t=[],i=this.headers[Y(e)];if(i)for(const s of i)t.push(s);else{const s=new RegExp("^\\s*"+e+"\\s*:","i");for(const r of this.extraHeaders)s.test(r)&&t.push(r.substring(r.indexOf(":")+1).trim())}return t}hasHeader(e){if(this.headers[Y(e)])return!0;{const t=new RegExp("^\\s*"+e+"\\s*:","i");for(const i of this.extraHeaders)if(t.test(i))return!0}return!1}setHeader(e,t){this.headers[Y(e)]=t instanceof Array?t:[t]}setViaHeader(e,t){this.options.hackViaTcp&&(t="TCP");let i="SIP/2.0/"+t;i+=" "+this.options.viaHost+";branch="+e,this.options.forceRport&&(i+=";rport"),this.setHeader("via",i),this.branch=e}toString(){let e="";e+=this.method+" "+this.ruri.toRaw()+` SIP/2.0\r
|
|
9
9
|
`;for(const t in this.headers)if(this.headers[t])for(const i of this.headers[t])e+=t+": "+i+`\r
|
|
10
10
|
`;for(const t of this.extraHeaders)e+=t.trim()+`\r
|
|
11
11
|
`;return e+="Supported: "+this.options.optionTags.join(", ")+`\r
|
|
12
12
|
`,e+="User-Agent: "+this.options.userAgentString+`\r
|
|
13
|
-
`,this.body?typeof this.body=="string"?(e+="Content-Length: "+
|
|
13
|
+
`,this.body?typeof this.body=="string"?(e+="Content-Length: "+Ce(this.body)+`\r
|
|
14
14
|
\r
|
|
15
15
|
`,e+=this.body):this.body.body&&this.body.contentType?(e+="Content-Type: "+this.body.contentType+`\r
|
|
16
|
-
`,e+="Content-Length: "+
|
|
16
|
+
`,e+="Content-Length: "+Ce(this.body.body)+`\r
|
|
17
17
|
\r
|
|
18
18
|
`,e+=this.body.body):e+=`Content-Length: 0\r
|
|
19
19
|
\r
|
|
20
20
|
`:e+=`Content-Length: 0\r
|
|
21
21
|
\r
|
|
22
|
-
`,e}}function rt(o){return o==="application/sdp"?"session":"render"}function $e(o){const e=typeof o=="string"?o:o.body,t=typeof o=="string"?"application/sdp":o.contentType;return{contentDisposition:rt(t),contentType:t,content:e}}function nt(o){return o&&typeof o.content=="string"&&typeof o.contentType=="string"&&o.contentDisposition===void 0?!0:typeof o.contentDisposition=="string"}function Ce(o){let e,t,i;if(o instanceof pe&&o.body){const s=o.parseHeader("Content-Disposition");e=s?s.type:void 0,t=o.parseHeader("Content-Type"),i=o.body}if(o instanceof se&&o.body){const s=o.parseHeader("Content-Disposition");e=s?s.type:void 0,t=o.parseHeader("Content-Type"),i=o.body}if(o instanceof he&&o.body)if(e=o.getHeader("Content-Disposition"),t=o.getHeader("Content-Type"),typeof o.body=="string"){if(!t)throw new Error("Header content type header does not equal body content type.");i=o.body}else{if(t&&t!==o.body.contentType)throw new Error("Header content type header does not equal body content type.");t=o.body.contentType,i=o.body.body}if(nt(o)&&(e=o.contentDisposition,t=o.contentType,i=o.content),!!i){if(t&&!e&&(e=rt(t)),!e)throw new Error("Content disposition undefined.");if(!t)throw new Error("Content type undefined.");return{contentDisposition:e,contentType:t,content:i}}}var V;(function(o){o.Initial="Initial",o.Early="Early",o.AckWait="AckWait",o.Confirmed="Confirmed",o.Terminated="Terminated"})(V=V||(V={}));var b;(function(o){o.Initial="Initial",o.HaveLocalOffer="HaveLocalOffer",o.HaveRemoteOffer="HaveRemoteOffer",o.Stable="Stable",o.Closed="Closed"})(b=b||(b={}));const ee=500,Ut=4e3,ot=5e3,M={T1:ee,T2:Ut,TIMER_B:64*ee,TIMER_D:0*ee,TIMER_F:64*ee,TIMER_H:64*ee,TIMER_I:0*ot,TIMER_J:0*ee,TIMER_K:0*ot,TIMER_L:64*ee,TIMER_M:64*ee,TIMER_N:64*ee,PROVISIONAL_RESPONSE_INTERVAL:6e4};class re extends de{constructor(e){super(e||"Transaction state error.")}}var v;(function(o){o.ACK="ACK",o.BYE="BYE",o.CANCEL="CANCEL",o.INFO="INFO",o.INVITE="INVITE",o.MESSAGE="MESSAGE",o.NOTIFY="NOTIFY",o.OPTIONS="OPTIONS",o.REGISTER="REGISTER",o.UPDATE="UPDATE",o.SUBSCRIBE="SUBSCRIBE",o.PUBLISH="PUBLISH",o.REFER="REFER",o.PRACK="PRACK"})(v=v||(v={}));const ne=[v.ACK,v.BYE,v.CANCEL,v.INFO,v.INVITE,v.MESSAGE,v.NOTIFY,v.OPTIONS,v.PRACK,v.REFER,v.REGISTER,v.SUBSCRIBE];class at{constructor(e){this.incomingMessageRequest=e}get request(){return this.incomingMessageRequest.message}accept(e){return this.incomingMessageRequest.accept(e),Promise.resolve()}reject(e){return this.incomingMessageRequest.reject(e),Promise.resolve()}}class Be{constructor(e){this.incomingNotifyRequest=e}get request(){return this.incomingNotifyRequest.message}accept(e){return this.incomingNotifyRequest.accept(e),Promise.resolve()}reject(e){return this.incomingNotifyRequest.reject(e),Promise.resolve()}}class Lt{constructor(e,t){this.incomingReferRequest=e,this.session=t}get referTo(){const e=this.incomingReferRequest.message.parseHeader("refer-to");if(!(e instanceof N))throw new Error("Failed to parse Refer-To header.");return e}get referredBy(){return this.incomingReferRequest.message.getHeader("referred-by")}get replaces(){const e=this.referTo.uri.getHeader("replaces");return e instanceof Array?e[0]:e}get request(){return this.incomingReferRequest.message}accept(e={statusCode:202}){return this.incomingReferRequest.accept(e),Promise.resolve()}reject(e){return this.incomingReferRequest.reject(e),Promise.resolve()}makeInviter(e){if(this.inviter)return this.inviter;const t=this.referTo.uri.clone();t.clearHeaders(),e=e||{};const i=(e.extraHeaders||[]).slice(),s=this.replaces;s&&i.push("Replaces: "+decodeURIComponent(s));const r=this.referredBy;return r&&i.push("Referred-By: "+r),e.extraHeaders=i,this.inviter=this.session.userAgent._makeInviter(t,e),this.inviter._referred=this.session,this.session._referral=this.inviter,this.inviter}}var m;(function(o){o.Initial="Initial",o.Establishing="Establishing",o.Established="Established",o.Terminating="Terminating",o.Terminated="Terminated"})(m=m||(m={}));class me{constructor(e,t={}){this.pendingReinvite=!1,this.pendingReinviteAck=!1,this._state=m.Initial,this.delegate=t.delegate,this._stateEventEmitter=new Se,this._userAgent=e}dispose(){switch(this.logger.log(`Session ${this.id} in state ${this._state} is being disposed`),delete this.userAgent._sessions[this.id],this._sessionDescriptionHandler&&this._sessionDescriptionHandler.close(),this.state){case m.Initial:break;case m.Establishing:break;case m.Established:return new Promise(e=>{this._bye({onAccept:()=>e(),onRedirect:()=>e(),onReject:()=>e()})});case m.Terminating:break;case m.Terminated:break;default:throw new Error("Unknown state.")}return Promise.resolve()}get assertedIdentity(){return this._assertedIdentity}get dialog(){return this._dialog}get id(){return this._id}get replacee(){return this._replacee}get sessionDescriptionHandler(){return this._sessionDescriptionHandler}get sessionDescriptionHandlerFactory(){return this.userAgent.configuration.sessionDescriptionHandlerFactory}get sessionDescriptionHandlerModifiers(){return this._sessionDescriptionHandlerModifiers||[]}set sessionDescriptionHandlerModifiers(e){this._sessionDescriptionHandlerModifiers=e.slice()}get sessionDescriptionHandlerOptions(){return this._sessionDescriptionHandlerOptions||{}}set sessionDescriptionHandlerOptions(e){this._sessionDescriptionHandlerOptions=Object.assign({},e)}get sessionDescriptionHandlerModifiersReInvite(){return this._sessionDescriptionHandlerModifiersReInvite||[]}set sessionDescriptionHandlerModifiersReInvite(e){this._sessionDescriptionHandlerModifiersReInvite=e.slice()}get sessionDescriptionHandlerOptionsReInvite(){return this._sessionDescriptionHandlerOptionsReInvite||{}}set sessionDescriptionHandlerOptionsReInvite(e){this._sessionDescriptionHandlerOptionsReInvite=Object.assign({},e)}get state(){return this._state}get stateChange(){return this._stateEventEmitter}get userAgent(){return this._userAgent}bye(e={}){let t="Session.bye() may only be called if established session.";switch(this.state){case m.Initial:typeof this.cancel=="function"?(t+=" However Inviter.invite() has not yet been called.",t+=" Perhaps you should have called Inviter.cancel()?"):typeof this.reject=="function"&&(t+=" However Invitation.accept() has not yet been called.",t+=" Perhaps you should have called Invitation.reject()?");break;case m.Establishing:typeof this.cancel=="function"?(t+=" However a dialog does not yet exist.",t+=" Perhaps you should have called Inviter.cancel()?"):typeof this.reject=="function"&&(t+=" However Invitation.accept() has not yet been called (or not yet resolved).",t+=" Perhaps you should have called Invitation.reject()?");break;case m.Established:{const i=e.requestDelegate,s=this.copyRequestOptions(e.requestOptions);return this._bye(i,s)}case m.Terminating:t+=" However this session is already terminating.",typeof this.cancel=="function"?t+=" Perhaps you have already called Inviter.cancel()?":typeof this.reject=="function"&&(t+=" Perhaps you have already called Session.bye()?");break;case m.Terminated:t+=" However this session is already terminated.";break;default:throw new Error("Unknown state")}return this.logger.error(t),Promise.reject(new Error(`Invalid session state ${this.state}`))}info(e={}){if(this.state!==m.Established)return this.logger.error("Session.info() may only be called if established session."),Promise.reject(new Error(`Invalid session state ${this.state}`));const t=e.requestDelegate,i=this.copyRequestOptions(e.requestOptions);return this._info(t,i)}invite(e={}){if(this.logger.log("Session.invite"),this.state!==m.Established)return Promise.reject(new Error(`Invalid session state ${this.state}`));if(this.pendingReinvite)return Promise.reject(new be("Reinvite in progress. Please wait until complete, then try again."));this.pendingReinvite=!0,e.sessionDescriptionHandlerModifiers&&(this.sessionDescriptionHandlerModifiersReInvite=e.sessionDescriptionHandlerModifiers),e.sessionDescriptionHandlerOptions&&(this.sessionDescriptionHandlerOptionsReInvite=e.sessionDescriptionHandlerOptions);const t={onAccept:r=>{const n=Ce(r.message);if(!n){this.logger.error("Received 2xx response to re-INVITE without a session description"),this.ackAndBye(r,400,"Missing session description"),this.stateTransition(m.Terminated),this.pendingReinvite=!1;return}if(e.withoutSdp){const a={sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptionsReInvite,sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiersReInvite};this.setOfferAndGetAnswer(n,a).then(d=>{r.ack({body:d})}).catch(d=>{this.logger.error("Failed to handle offer in 2xx response to re-INVITE"),this.logger.error(d.message),this.state===m.Terminated?r.ack():(this.ackAndBye(r,488,"Bad Media Description"),this.stateTransition(m.Terminated))}).then(()=>{this.pendingReinvite=!1,e.requestDelegate&&e.requestDelegate.onAccept&&e.requestDelegate.onAccept(r)})}else{const a={sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptionsReInvite,sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiersReInvite};this.setAnswer(n,a).then(()=>{r.ack()}).catch(d=>{this.logger.error("Failed to handle answer in 2xx response to re-INVITE"),this.logger.error(d.message),this.state!==m.Terminated?(this.ackAndBye(r,488,"Bad Media Description"),this.stateTransition(m.Terminated)):r.ack()}).then(()=>{this.pendingReinvite=!1,e.requestDelegate&&e.requestDelegate.onAccept&&e.requestDelegate.onAccept(r)})}},onProgress:r=>{},onRedirect:r=>{},onReject:r=>{this.logger.warn("Received a non-2xx response to re-INVITE"),this.pendingReinvite=!1,e.withoutSdp?e.requestDelegate&&e.requestDelegate.onReject&&e.requestDelegate.onReject(r):this.rollbackOffer().catch(n=>{if(this.logger.error("Failed to rollback offer on non-2xx response to re-INVITE"),this.logger.error(n.message),this.state!==m.Terminated){if(!this.dialog)throw new Error("Dialog undefined.");const a=[];a.push("Reason: "+this.getReasonHeaderValue(500,"Internal Server Error")),this.dialog.bye(void 0,{extraHeaders:a}),this.stateTransition(m.Terminated)}}).then(()=>{e.requestDelegate&&e.requestDelegate.onReject&&e.requestDelegate.onReject(r)})},onTrying:r=>{}},i=e.requestOptions||{};if(i.extraHeaders=(i.extraHeaders||[]).slice(),i.extraHeaders.push("Allow: "+ne.toString()),i.extraHeaders.push("Contact: "+this._contact),e.withoutSdp){if(!this.dialog)throw this.pendingReinvite=!1,new Error("Dialog undefined.");return Promise.resolve(this.dialog.invite(t,i))}const s={sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptionsReInvite,sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiersReInvite};return this.getOffer(s).then(r=>{if(!this.dialog)throw this.pendingReinvite=!1,new Error("Dialog undefined.");return i.body=r,this.dialog.invite(t,i)}).catch(r=>{throw this.logger.error(r.message),this.logger.error("Failed to send re-INVITE"),this.pendingReinvite=!1,r})}message(e={}){if(this.state!==m.Established)return this.logger.error("Session.message() may only be called if established session."),Promise.reject(new Error(`Invalid session state ${this.state}`));const t=e.requestDelegate,i=this.copyRequestOptions(e.requestOptions);return this._message(t,i)}refer(e,t={}){if(this.state!==m.Established)return this.logger.error("Session.refer() may only be called if established session."),Promise.reject(new Error(`Invalid session state ${this.state}`));if(e instanceof me&&!e.dialog)return this.logger.error("Session.refer() may only be called with session which is established. You are perhaps attempting to attended transfer to a target for which there is not dialog yet established. Perhaps you are attempting a 'semi-attended' tansfer? Regardless, this is not supported. The recommended approached is to check to see if the target Session is in the Established state before calling refer(); if the state is not Established you may proceed by falling back using a URI as the target (blind transfer)."),Promise.reject(new Error(`Invalid session state ${this.state}`));const i=t.requestDelegate,s=this.copyRequestOptions(t.requestOptions);return s.extraHeaders=s.extraHeaders?s.extraHeaders.concat(this.referExtraHeaders(this.referToString(e))):this.referExtraHeaders(this.referToString(e)),this._refer(t.onNotify,i,s)}_bye(e,t){if(!this.dialog)return Promise.reject(new Error("Session dialog undefined."));const i=this.dialog;switch(i.sessionState){case V.Initial:throw new Error(`Invalid dialog state ${i.sessionState}`);case V.Early:throw new Error(`Invalid dialog state ${i.sessionState}`);case V.AckWait:return this.stateTransition(m.Terminating),new Promise(s=>{i.delegate={onAck:()=>{const r=i.bye(e,t);return this.stateTransition(m.Terminated),s(r),Promise.resolve()},onAckTimeout:()=>{const r=i.bye(e,t);this.stateTransition(m.Terminated),s(r)}}});case V.Confirmed:{const s=i.bye(e,t);return this.stateTransition(m.Terminated),Promise.resolve(s)}case V.Terminated:throw new Error(`Invalid dialog state ${i.sessionState}`);default:throw new Error("Unrecognized state.")}}_info(e,t){return this.dialog?Promise.resolve(this.dialog.info(e,t)):Promise.reject(new Error("Session dialog undefined."))}_message(e,t){return this.dialog?Promise.resolve(this.dialog.message(e,t)):Promise.reject(new Error("Session dialog undefined."))}_refer(e,t,i){return this.dialog?(this.onNotify=e,Promise.resolve(this.dialog.refer(t,i))):Promise.reject(new Error("Session dialog undefined."))}ackAndBye(e,t,i){e.ack();const s=[];t&&s.push("Reason: "+this.getReasonHeaderValue(t,i)),e.session.bye(void 0,{extraHeaders:s})}onAckRequest(e){if(this.logger.log("Session.onAckRequest"),this.state!==m.Established&&this.state!==m.Terminating)return this.logger.error(`ACK received while in state ${this.state}, dropping request`),Promise.resolve();const t=this.dialog;if(!t)throw new Error("Dialog undefined.");const i={sessionDescriptionHandlerOptions:this.pendingReinviteAck?this.sessionDescriptionHandlerOptionsReInvite:this.sessionDescriptionHandlerOptions,sessionDescriptionHandlerModifiers:this.pendingReinviteAck?this._sessionDescriptionHandlerModifiersReInvite:this._sessionDescriptionHandlerModifiers};if(this.delegate&&this.delegate.onAck){const s=new Pt(e);this.delegate.onAck(s)}switch(this.pendingReinviteAck=!1,t.signalingState){case b.Initial:{this.logger.error(`Invalid signaling state ${t.signalingState}.`);const s=["Reason: "+this.getReasonHeaderValue(488,"Bad Media Description")];return t.bye(void 0,{extraHeaders:s}),this.stateTransition(m.Terminated),Promise.resolve()}case b.Stable:{const s=Ce(e.message);return s?s.contentDisposition==="render"?(this._renderbody=s.content,this._rendertype=s.contentType,Promise.resolve()):s.contentDisposition!=="session"?Promise.resolve():this.setAnswer(s,i).catch(r=>{this.logger.error(r.message);const n=["Reason: "+this.getReasonHeaderValue(488,"Bad Media Description")];t.bye(void 0,{extraHeaders:n}),this.stateTransition(m.Terminated)}):Promise.resolve()}case b.HaveLocalOffer:{this.logger.error(`Invalid signaling state ${t.signalingState}.`);const s=["Reason: "+this.getReasonHeaderValue(488,"Bad Media Description")];return t.bye(void 0,{extraHeaders:s}),this.stateTransition(m.Terminated),Promise.resolve()}case b.HaveRemoteOffer:{this.logger.error(`Invalid signaling state ${t.signalingState}.`);const s=["Reason: "+this.getReasonHeaderValue(488,"Bad Media Description")];return t.bye(void 0,{extraHeaders:s}),this.stateTransition(m.Terminated),Promise.resolve()}case b.Closed:throw new Error(`Invalid signaling state ${t.signalingState}.`);default:throw new Error(`Invalid signaling state ${t.signalingState}.`)}}onByeRequest(e){if(this.logger.log("Session.onByeRequest"),this.state!==m.Established){this.logger.error(`BYE received while in state ${this.state}, dropping request`);return}if(this.delegate&&this.delegate.onBye){const t=new Ht(e);this.delegate.onBye(t)}else e.accept();this.stateTransition(m.Terminated)}onInfoRequest(e){if(this.logger.log("Session.onInfoRequest"),this.state!==m.Established){this.logger.error(`INFO received while in state ${this.state}, dropping request`);return}if(this.delegate&&this.delegate.onInfo){const t=new qt(e);this.delegate.onInfo(t)}else e.accept()}onInviteRequest(e){if(this.logger.log("Session.onInviteRequest"),this.state!==m.Established){this.logger.error(`INVITE received while in state ${this.state}, dropping request`);return}this.pendingReinviteAck=!0;const t=["Contact: "+this._contact];if(e.message.hasHeader("P-Asserted-Identity")){const s=e.message.getHeader("P-Asserted-Identity");if(!s)throw new Error("Header undefined.");this._assertedIdentity=k.nameAddrHeaderParse(s)}const i={sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptionsReInvite,sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiersReInvite};this.generateResponseOfferAnswerInDialog(i).then(s=>{const r=e.accept({statusCode:200,extraHeaders:t,body:s});this.delegate&&this.delegate.onInvite&&this.delegate.onInvite(e.message,r.message,200)}).catch(s=>{if(this.logger.error(s.message),this.logger.error("Failed to handle to re-INVITE request"),!this.dialog)throw new Error("Dialog undefined.");if(this.logger.error(this.dialog.signalingState),this.dialog.signalingState===b.Stable){const r=e.reject({statusCode:488});this.delegate&&this.delegate.onInvite&&this.delegate.onInvite(e.message,r.message,488);return}this.rollbackOffer().then(()=>{const r=e.reject({statusCode:488});this.delegate&&this.delegate.onInvite&&this.delegate.onInvite(e.message,r.message,488)}).catch(r=>{this.logger.error(r.message),this.logger.error("Failed to rollback offer on re-INVITE request");const n=e.reject({statusCode:488});if(this.state!==m.Terminated){if(!this.dialog)throw new Error("Dialog undefined.");const a=[];a.push("Reason: "+this.getReasonHeaderValue(500,"Internal Server Error")),this.dialog.bye(void 0,{extraHeaders:a}),this.stateTransition(m.Terminated)}this.delegate&&this.delegate.onInvite&&this.delegate.onInvite(e.message,n.message,488)})})}onMessageRequest(e){if(this.logger.log("Session.onMessageRequest"),this.state!==m.Established){this.logger.error(`MESSAGE received while in state ${this.state}, dropping request`);return}if(this.delegate&&this.delegate.onMessage){const t=new at(e);this.delegate.onMessage(t)}else e.accept()}onNotifyRequest(e){if(this.logger.log("Session.onNotifyRequest"),this.state!==m.Established){this.logger.error(`NOTIFY received while in state ${this.state}, dropping request`);return}if(this.onNotify){const t=new Be(e);this.onNotify(t);return}if(this.delegate&&this.delegate.onNotify){const t=new Be(e);this.delegate.onNotify(t)}else e.accept()}onPrackRequest(e){if(this.logger.log("Session.onPrackRequest"),this.state!==m.Established){this.logger.error(`PRACK received while in state ${this.state}, dropping request`);return}throw new Error("Unimplemented.")}onReferRequest(e){if(this.logger.log("Session.onReferRequest"),this.state!==m.Established){this.logger.error(`REFER received while in state ${this.state}, dropping request`);return}if(!e.message.hasHeader("refer-to")){this.logger.warn("Invalid REFER packet. A refer-to header is required. Rejecting."),e.reject();return}const t=new Lt(e,this);this.delegate&&this.delegate.onRefer?this.delegate.onRefer(t):(this.logger.log("No delegate available to handle REFER, automatically accepting and following."),t.accept().then(()=>t.makeInviter(this._referralInviterOptions).invite()).catch(i=>{this.logger.error(i.message)}))}generateResponseOfferAnswer(e,t){if(this.dialog)return this.generateResponseOfferAnswerInDialog(t);const i=Ce(e.message);return!i||i.contentDisposition!=="session"?this.getOffer(t):this.setOfferAndGetAnswer(i,t)}generateResponseOfferAnswerInDialog(e){if(!this.dialog)throw new Error("Dialog undefined.");switch(this.dialog.signalingState){case b.Initial:return this.getOffer(e);case b.HaveLocalOffer:return Promise.resolve(void 0);case b.HaveRemoteOffer:if(!this.dialog.offer)throw new Error(`Session offer undefined in signaling state ${this.dialog.signalingState}.`);return this.setOfferAndGetAnswer(this.dialog.offer,e);case b.Stable:return this.state!==m.Established?Promise.resolve(void 0):this.getOffer(e);case b.Closed:throw new Error(`Invalid signaling state ${this.dialog.signalingState}.`);default:throw new Error(`Invalid signaling state ${this.dialog.signalingState}.`)}}getOffer(e){const t=this.setupSessionDescriptionHandler(),i=e.sessionDescriptionHandlerOptions,s=e.sessionDescriptionHandlerModifiers;try{return t.getDescription(i,s).then(r=>$e(r)).catch(r=>{this.logger.error("Session.getOffer: SDH getDescription rejected...");const n=r instanceof Error?r:new Error("Session.getOffer unknown error.");throw this.logger.error(n.message),n})}catch(r){this.logger.error("Session.getOffer: SDH getDescription threw...");const n=r instanceof Error?r:new Error(r);return this.logger.error(n.message),Promise.reject(n)}}rollbackOffer(){const e=this.setupSessionDescriptionHandler();if(e.rollbackDescription===void 0)return Promise.resolve();try{return e.rollbackDescription().catch(t=>{this.logger.error("Session.rollbackOffer: SDH rollbackDescription rejected...");const i=t instanceof Error?t:new Error("Session.rollbackOffer unknown error.");throw this.logger.error(i.message),i})}catch(t){this.logger.error("Session.rollbackOffer: SDH rollbackDescription threw...");const i=t instanceof Error?t:new Error(t);return this.logger.error(i.message),Promise.reject(i)}}setAnswer(e,t){const i=this.setupSessionDescriptionHandler(),s=t.sessionDescriptionHandlerOptions,r=t.sessionDescriptionHandlerModifiers;try{if(!i.hasDescription(e.contentType))return Promise.reject(new Ne)}catch(n){this.logger.error("Session.setAnswer: SDH hasDescription threw...");const a=n instanceof Error?n:new Error(n);return this.logger.error(a.message),Promise.reject(a)}try{return i.setDescription(e.content,s,r).catch(n=>{this.logger.error("Session.setAnswer: SDH setDescription rejected...");const a=n instanceof Error?n:new Error("Session.setAnswer unknown error.");throw this.logger.error(a.message),a})}catch(n){this.logger.error("Session.setAnswer: SDH setDescription threw...");const a=n instanceof Error?n:new Error(n);return this.logger.error(a.message),Promise.reject(a)}}setOfferAndGetAnswer(e,t){const i=this.setupSessionDescriptionHandler(),s=t.sessionDescriptionHandlerOptions,r=t.sessionDescriptionHandlerModifiers;try{if(!i.hasDescription(e.contentType))return Promise.reject(new Ne)}catch(n){this.logger.error("Session.setOfferAndGetAnswer: SDH hasDescription threw...");const a=n instanceof Error?n:new Error(n);return this.logger.error(a.message),Promise.reject(a)}try{return i.setDescription(e.content,s,r).then(()=>i.getDescription(s,r)).then(n=>$e(n)).catch(n=>{this.logger.error("Session.setOfferAndGetAnswer: SDH setDescription or getDescription rejected...");const a=n instanceof Error?n:new Error("Session.setOfferAndGetAnswer unknown error.");throw this.logger.error(a.message),a})}catch(n){this.logger.error("Session.setOfferAndGetAnswer: SDH setDescription or getDescription threw...");const a=n instanceof Error?n:new Error(n);return this.logger.error(a.message),Promise.reject(a)}}setSessionDescriptionHandler(e){if(this._sessionDescriptionHandler)throw new Error("Session description handler defined.");this._sessionDescriptionHandler=e}setupSessionDescriptionHandler(){var e;return this._sessionDescriptionHandler?this._sessionDescriptionHandler:(this._sessionDescriptionHandler=this.sessionDescriptionHandlerFactory(this,this.userAgent.configuration.sessionDescriptionHandlerFactoryOptions),!((e=this.delegate)===null||e===void 0)&&e.onSessionDescriptionHandler&&this.delegate.onSessionDescriptionHandler(this._sessionDescriptionHandler,!1),this._sessionDescriptionHandler)}stateTransition(e){const t=()=>{throw new Error(`Invalid state transition from ${this._state} to ${e}`)};switch(this._state){case m.Initial:e!==m.Establishing&&e!==m.Established&&e!==m.Terminating&&e!==m.Terminated&&t();break;case m.Establishing:e!==m.Established&&e!==m.Terminating&&e!==m.Terminated&&t();break;case m.Established:e!==m.Terminating&&e!==m.Terminated&&t();break;case m.Terminating:e!==m.Terminated&&t();break;case m.Terminated:t();break;default:throw new Error("Unrecognized state.")}this._state=e,this.logger.log(`Session ${this.id} transitioned to state ${this._state}`),this._stateEventEmitter.emit(this._state),e===m.Terminated&&this.dispose()}copyRequestOptions(e={}){const t=e.extraHeaders?e.extraHeaders.slice():void 0,i=e.body?{contentDisposition:e.body.contentDisposition||"render",contentType:e.body.contentType||"text/plain",content:e.body.content||""}:void 0;return{extraHeaders:t,body:i}}getReasonHeaderValue(e,t){const i=e;let s=Ie(e);return!s&&t&&(s=t),"SIP;cause="+i+';text="'+s+'"'}referExtraHeaders(e){const t=[];return t.push("Referred-By: <"+this.userAgent.configuration.uri+">"),t.push("Contact: "+this._contact),t.push("Allow: "+["ACK","CANCEL","INVITE","MESSAGE","BYE","OPTIONS","INFO","NOTIFY","REFER"].toString()),t.push("Refer-To: "+e),t}referToString(e){let t;if(e instanceof z)t=e.toString();else{if(!e.dialog)throw new Error("Dialog undefined.");const i=e.remoteIdentity.friendlyName,s=e.dialog.remoteTarget.toString(),r=e.dialog.callId,n=e.dialog.remoteTag,a=e.dialog.localTag,d=encodeURIComponent(`${r};to-tag=${n};from-tag=${a}`);t=`"${i}" <${s}?Replaces=${d}>`}return t}}var W;(function(o){o.Required="Required",o.Supported="Supported",o.Unsupported="Unsupported"})(W=W||(W={}));const Bt={"100rel":!0,199:!0,answermode:!0,"early-session":!0,eventlist:!0,explicitsub:!0,"from-change":!0,"geolocation-http":!0,"geolocation-sip":!0,gin:!0,gruu:!0,histinfo:!0,ice:!0,join:!0,"multiple-refer":!0,norefersub:!0,nosub:!0,outbound:!0,path:!0,policy:!0,precondition:!0,pref:!0,privacy:!0,"recipient-list-invite":!0,"recipient-list-message":!0,"recipient-list-subscribe":!0,replaces:!0,"resource-priority":!0,"sdp-anat":!0,"sec-agree":!0,tdialog:!0,timer:!0,uui:!0};class ue extends me{constructor(e,t){super(e),this.incomingInviteRequest=t,this.disposed=!1,this.expiresTimer=void 0,this.isCanceled=!1,this.rel100="none",this.rseq=Math.floor(Math.random()*1e4),this.userNoAnswerTimer=void 0,this.waitingForPrack=!1,this.logger=e.getLogger("sip.Invitation");const i=this.incomingInviteRequest.message,s=i.getHeader("require");s&&s.toLowerCase().includes("100rel")&&(this.rel100="required");const r=i.getHeader("supported");if(r&&r.toLowerCase().includes("100rel")&&(this.rel100="supported"),i.toTag=t.toTag,typeof i.toTag!="string")throw new TypeError("toTag should have been a string.");if(this.userNoAnswerTimer=setTimeout(()=>{t.reject({statusCode:480}),this.stateTransition(m.Terminated)},this.userAgent.configuration.noAnswerTimeout?this.userAgent.configuration.noAnswerTimeout*1e3:6e4),i.hasHeader("expires")){const d=Number(i.getHeader("expires")||0)*1e3;this.expiresTimer=setTimeout(()=>{this.state===m.Initial&&(t.reject({statusCode:487}),this.stateTransition(m.Terminated))},d)}const n=this.request.getHeader("P-Asserted-Identity");n&&(this._assertedIdentity=k.nameAddrHeaderParse(n)),this._contact=this.userAgent.contact.toString();const a=i.parseHeader("Content-Disposition");a&&a.type==="render"&&(this._renderbody=i.body,this._rendertype=i.getHeader("Content-Type")),this._id=i.callId+i.fromTag,this.userAgent._sessions[this._id]=this}dispose(){if(this.disposed)return Promise.resolve();switch(this.disposed=!0,this.expiresTimer&&(clearTimeout(this.expiresTimer),this.expiresTimer=void 0),this.userNoAnswerTimer&&(clearTimeout(this.userNoAnswerTimer),this.userNoAnswerTimer=void 0),this.prackNeverArrived(),this.state){case m.Initial:return this.reject().then(()=>super.dispose());case m.Establishing:return this.reject().then(()=>super.dispose());case m.Established:return super.dispose();case m.Terminating:return super.dispose();case m.Terminated:return super.dispose();default:throw new Error("Unknown state.")}}get autoSendAnInitialProvisionalResponse(){return this.rel100!=="required"&&this.userAgent.configuration.sendInitialProvisionalResponse}get body(){return this.incomingInviteRequest.message.body}get localIdentity(){return this.request.to}get remoteIdentity(){return this.request.from}get request(){return this.incomingInviteRequest.message}accept(e={}){if(this.logger.log("Invitation.accept"),this.state!==m.Initial){const t=new Error(`Invalid session state ${this.state}`);return this.logger.error(t.message),Promise.reject(t)}return e.sessionDescriptionHandlerModifiers&&(this.sessionDescriptionHandlerModifiers=e.sessionDescriptionHandlerModifiers),e.sessionDescriptionHandlerOptions&&(this.sessionDescriptionHandlerOptions=e.sessionDescriptionHandlerOptions),this.stateTransition(m.Establishing),this.sendAccept(e).then(({message:t,session:i})=>{i.delegate={onAck:s=>this.onAckRequest(s),onAckTimeout:()=>this.onAckTimeout(),onBye:s=>this.onByeRequest(s),onInfo:s=>this.onInfoRequest(s),onInvite:s=>this.onInviteRequest(s),onMessage:s=>this.onMessageRequest(s),onNotify:s=>this.onNotifyRequest(s),onPrack:s=>this.onPrackRequest(s),onRefer:s=>this.onReferRequest(s)},this._dialog=i,this.stateTransition(m.Established),this._replacee&&this._replacee._bye()}).catch(t=>this.handleResponseError(t))}progress(e={}){if(this.logger.log("Invitation.progress"),this.state!==m.Initial){const i=new Error(`Invalid session state ${this.state}`);return this.logger.error(i.message),Promise.reject(i)}const t=e.statusCode||180;if(t<100||t>199)throw new TypeError("Invalid statusCode: "+t);return e.sessionDescriptionHandlerModifiers&&(this.sessionDescriptionHandlerModifiers=e.sessionDescriptionHandlerModifiers),e.sessionDescriptionHandlerOptions&&(this.sessionDescriptionHandlerOptions=e.sessionDescriptionHandlerOptions),this.waitingForPrack?(this.logger.warn("Unexpected call for progress while waiting for prack, ignoring"),Promise.resolve()):e.statusCode===100?this.sendProgressTrying().then(()=>{}).catch(i=>this.handleResponseError(i)):this.rel100!=="required"&&!(this.rel100==="supported"&&e.rel100)&&!(this.rel100==="supported"&&this.userAgent.configuration.sipExtension100rel===W.Required)?this.sendProgress(e).then(()=>{}).catch(i=>this.handleResponseError(i)):this.sendProgressReliableWaitForPrack(e).then(()=>{}).catch(i=>this.handleResponseError(i))}reject(e={}){if(this.logger.log("Invitation.reject"),this.state!==m.Initial&&this.state!==m.Establishing){const n=new Error(`Invalid session state ${this.state}`);return this.logger.error(n.message),Promise.reject(n)}const t=e.statusCode||480,i=e.reasonPhrase?e.reasonPhrase:Ie(t),s=e.extraHeaders||[];if(t<300||t>699)throw new TypeError("Invalid statusCode: "+t);const r=e.body?$e(e.body):void 0;return t<400?this.incomingInviteRequest.redirect([],{statusCode:t,reasonPhrase:i,extraHeaders:s,body:r}):this.incomingInviteRequest.reject({statusCode:t,reasonPhrase:i,extraHeaders:s,body:r}),this.stateTransition(m.Terminated),Promise.resolve()}_onCancel(e){if(this.logger.log("Invitation._onCancel"),this.state!==m.Initial&&this.state!==m.Establishing){this.logger.error(`CANCEL received while in state ${this.state}, dropping request`);return}if(this.delegate&&this.delegate.onCancel){const t=new Mt(e);this.delegate.onCancel(t)}this.isCanceled=!0,this.incomingInviteRequest.reject({statusCode:487}),this.stateTransition(m.Terminated)}handlePrackOfferAnswer(e){if(!this.dialog)throw new Error("Dialog undefined.");const t=Ce(e.message);if(!t||t.contentDisposition!=="session")return Promise.resolve(void 0);const i={sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptions,sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiers};switch(this.dialog.signalingState){case b.Initial:throw new Error(`Invalid signaling state ${this.dialog.signalingState}.`);case b.Stable:return this.setAnswer(t,i).then(()=>{});case b.HaveLocalOffer:throw new Error(`Invalid signaling state ${this.dialog.signalingState}.`);case b.HaveRemoteOffer:return this.setOfferAndGetAnswer(t,i);case b.Closed:throw new Error(`Invalid signaling state ${this.dialog.signalingState}.`);default:throw new Error(`Invalid signaling state ${this.dialog.signalingState}.`)}}handleResponseError(e){let t=480;if(e instanceof Error?this.logger.error(e.message):this.logger.error(e),e instanceof Ne?(this.logger.error("A session description handler occurred while sending response (content type unsupported"),t=415):e instanceof kt?this.logger.error("A session description handler occurred while sending response"):e instanceof Ue?this.logger.error("Session ended before response could be formulated and sent (while waiting for PRACK)"):e instanceof re&&this.logger.error("Session changed state before response could be formulated and sent"),this.state===m.Initial||this.state===m.Establishing)try{this.incomingInviteRequest.reject({statusCode:t}),this.stateTransition(m.Terminated)}catch(i){throw this.logger.error("An error occurred attempting to reject the request while handling another error"),i}if(this.isCanceled){this.logger.warn("An error occurred while attempting to formulate and send a response to an incoming INVITE. However a CANCEL was received and processed while doing so which can (and often does) result in errors occurring as the session terminates in the meantime. Said error is being ignored.");return}throw e}onAckTimeout(){if(this.logger.log("Invitation.onAckTimeout"),!this.dialog)throw new Error("Dialog undefined.");this.logger.log("No ACK received for an extended period of time, terminating session"),this.dialog.bye(),this.stateTransition(m.Terminated)}sendAccept(e={}){const t={sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptions,sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiers},i=e.extraHeaders||[];return this.waitingForPrack?this.waitForArrivalOfPrack().then(()=>clearTimeout(this.userNoAnswerTimer)).then(()=>this.generateResponseOfferAnswer(this.incomingInviteRequest,t)).then(s=>this.incomingInviteRequest.accept({statusCode:200,body:s,extraHeaders:i})):(clearTimeout(this.userNoAnswerTimer),this.generateResponseOfferAnswer(this.incomingInviteRequest,t).then(s=>this.incomingInviteRequest.accept({statusCode:200,body:s,extraHeaders:i})))}sendProgress(e={}){const t=e.statusCode||180,i=e.reasonPhrase,s=(e.extraHeaders||[]).slice(),r=e.body?$e(e.body):void 0;if(t===183&&!r)return this.sendProgressWithSDP(e);try{const n=this.incomingInviteRequest.progress({statusCode:t,reasonPhrase:i,extraHeaders:s,body:r});return this._dialog=n.session,Promise.resolve(n)}catch(n){return Promise.reject(n)}}sendProgressWithSDP(e={}){const t={sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptions,sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiers},i=e.statusCode||183,s=e.reasonPhrase,r=(e.extraHeaders||[]).slice();return this.generateResponseOfferAnswer(this.incomingInviteRequest,t).then(n=>this.incomingInviteRequest.progress({statusCode:i,reasonPhrase:s,extraHeaders:r,body:n})).then(n=>(this._dialog=n.session,n))}sendProgressReliable(e={}){return e.extraHeaders=(e.extraHeaders||[]).slice(),e.extraHeaders.push("Require: 100rel"),e.extraHeaders.push("RSeq: "+Math.floor(Math.random()*1e4)),this.sendProgressWithSDP(e)}sendProgressReliableWaitForPrack(e={}){const t={sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptions,sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiers},i=e.statusCode||183,s=e.reasonPhrase,r=(e.extraHeaders||[]).slice();r.push("Require: 100rel"),r.push("RSeq: "+this.rseq++);let n;return new Promise((a,d)=>{this.waitingForPrack=!0,this.generateResponseOfferAnswer(this.incomingInviteRequest,t).then(f=>(n=f,this.incomingInviteRequest.progress({statusCode:i,reasonPhrase:s,extraHeaders:r,body:n}))).then(f=>{this._dialog=f.session;let h,w;f.session.delegate={onPrack:p=>{h=p,clearTimeout(x),clearTimeout(ge),this.waitingForPrack&&(this.waitingForPrack=!1,this.handlePrackOfferAnswer(h).then($=>{try{w=h.accept({statusCode:200,body:$}),this.prackArrived(),a({prackRequest:h,prackResponse:w,progressResponse:f})}catch(Qe){d(Qe)}}).catch($=>d($)))}};const x=setTimeout(()=>{this.waitingForPrack&&(this.waitingForPrack=!1,this.logger.warn("No PRACK received, rejecting INVITE."),clearTimeout(ge),this.reject({statusCode:504}).then(()=>d(new Ue)).catch(p=>d(p)))},M.T1*64),I=()=>{try{this.incomingInviteRequest.progress({statusCode:i,reasonPhrase:s,extraHeaders:r,body:n})}catch(p){this.waitingForPrack=!1,d(p);return}ge=setTimeout(I,E*=2)};let E=M.T1,ge=setTimeout(I,E)}).catch(f=>{this.waitingForPrack=!1,d(f)})})}sendProgressTrying(){try{const e=this.incomingInviteRequest.trying();return Promise.resolve(e)}catch(e){return Promise.reject(e)}}waitForArrivalOfPrack(){if(this.waitingForPrackPromise)throw new Error("Already waiting for PRACK");return this.waitingForPrackPromise=new Promise((e,t)=>{this.waitingForPrackResolve=e,this.waitingForPrackReject=t}),this.waitingForPrackPromise}prackArrived(){this.waitingForPrackResolve&&this.waitingForPrackResolve(),this.waitingForPrackPromise=void 0,this.waitingForPrackResolve=void 0,this.waitingForPrackReject=void 0}prackNeverArrived(){this.waitingForPrackReject&&this.waitingForPrackReject(new Ue),this.waitingForPrackPromise=void 0,this.waitingForPrackResolve=void 0,this.waitingForPrackReject=void 0}}class De extends me{constructor(e,t,i={}){super(e,i),this.disposed=!1,this.earlyMedia=!1,this.earlyMediaSessionDescriptionHandlers=new Map,this.isCanceled=!1,this.inviteWithoutSdp=!1,this.logger=e.getLogger("sip.Inviter"),this.earlyMedia=i.earlyMedia!==void 0?i.earlyMedia:this.earlyMedia,this.fromTag=Ae(),this.inviteWithoutSdp=i.inviteWithoutSdp!==void 0?i.inviteWithoutSdp:this.inviteWithoutSdp;const s=Object.assign({},i);s.params=Object.assign({},i.params);const r=i.anonymous||!1,n=e.contact.toString({anonymous:r,outbound:r?!e.contact.tempGruu:!e.contact.pubGruu});r&&e.configuration.uri&&(s.params.fromDisplayName="Anonymous",s.params.fromUri="sip:anonymous@anonymous.invalid");let a=e.userAgentCore.configuration.aor;if(s.params.fromUri&&(a=typeof s.params.fromUri=="string"?k.URIParse(s.params.fromUri):s.params.fromUri),!a)throw new TypeError("Invalid from URI: "+s.params.fromUri);let d=t;if(s.params.toUri&&(d=typeof s.params.toUri=="string"?k.URIParse(s.params.toUri):s.params.toUri),!d)throw new TypeError("Invalid to URI: "+s.params.toUri);const f=Object.assign({},s.params);f.fromTag=this.fromTag;const h=(s.extraHeaders||[]).slice();r&&e.configuration.uri&&(h.push("P-Preferred-Identity: "+e.configuration.uri.toString()),h.push("Privacy: id")),h.push("Contact: "+n),h.push("Allow: "+["ACK","CANCEL","INVITE","MESSAGE","BYE","OPTIONS","INFO","NOTIFY","REFER"].toString()),e.configuration.sipExtension100rel===W.Required&&h.push("Require: 100rel"),e.configuration.sipExtensionReplaces===W.Required&&h.push("Require: replaces"),s.extraHeaders=h;const w=void 0;this.outgoingRequestMessage=e.userAgentCore.makeOutgoingRequestMessage(v.INVITE,t,a,d,f,h,w),this._contact=n,this._referralInviterOptions=s,this._renderbody=i.renderbody,this._rendertype=i.rendertype,i.sessionDescriptionHandlerModifiers&&(this.sessionDescriptionHandlerModifiers=i.sessionDescriptionHandlerModifiers),i.sessionDescriptionHandlerOptions&&(this.sessionDescriptionHandlerOptions=i.sessionDescriptionHandlerOptions),i.sessionDescriptionHandlerModifiersReInvite&&(this.sessionDescriptionHandlerModifiersReInvite=i.sessionDescriptionHandlerModifiersReInvite),i.sessionDescriptionHandlerOptionsReInvite&&(this.sessionDescriptionHandlerOptionsReInvite=i.sessionDescriptionHandlerOptionsReInvite),this._id=this.outgoingRequestMessage.callId+this.fromTag,this.userAgent._sessions[this._id]=this}dispose(){if(this.disposed)return Promise.resolve();switch(this.disposed=!0,this.disposeEarlyMedia(),this.state){case m.Initial:return this.cancel().then(()=>super.dispose());case m.Establishing:return this.cancel().then(()=>super.dispose());case m.Established:return super.dispose();case m.Terminating:return super.dispose();case m.Terminated:return super.dispose();default:throw new Error("Unknown state.")}}get body(){return this.outgoingRequestMessage.body}get localIdentity(){return this.outgoingRequestMessage.from}get remoteIdentity(){return this.outgoingRequestMessage.to}get request(){return this.outgoingRequestMessage}cancel(e={}){if(this.logger.log("Inviter.cancel"),this.state!==m.Initial&&this.state!==m.Establishing){const i=new Error(`Invalid session state ${this.state}`);return this.logger.error(i.message),Promise.reject(i)}this.isCanceled=!0,this.stateTransition(m.Terminating);function t(i,s){if(i&&i<200||i>699)throw new TypeError("Invalid statusCode: "+i);if(i){const r=i,n=Ie(i)||s;return"SIP;cause="+r+';text="'+n+'"'}}if(this.outgoingInviteRequest){let i;e.statusCode&&e.reasonPhrase&&(i=t(e.statusCode,e.reasonPhrase)),this.outgoingInviteRequest.cancel(i,e)}else this.logger.warn("Canceled session before INVITE was sent"),this.stateTransition(m.Terminated);return Promise.resolve()}invite(e={}){if(this.logger.log("Inviter.invite"),this.state!==m.Initial)return super.invite(e);if(e.sessionDescriptionHandlerModifiers&&(this.sessionDescriptionHandlerModifiers=e.sessionDescriptionHandlerModifiers),e.sessionDescriptionHandlerOptions&&(this.sessionDescriptionHandlerOptions=e.sessionDescriptionHandlerOptions),e.withoutSdp||this.inviteWithoutSdp)return this._renderbody&&this._rendertype&&(this.outgoingRequestMessage.body={contentType:this._rendertype,body:this._renderbody}),this.stateTransition(m.Establishing),Promise.resolve(this.sendInvite(e));const t={sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiers,sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptions};return this.getOffer(t).then(i=>(this.outgoingRequestMessage.body={body:i.content,contentType:i.contentType},this.stateTransition(m.Establishing),this.sendInvite(e))).catch(i=>{throw this.logger.log(i.message),this.state!==m.Terminated&&this.stateTransition(m.Terminated),i})}sendInvite(e={}){return this.outgoingInviteRequest=this.userAgent.userAgentCore.invite(this.outgoingRequestMessage,{onAccept:t=>{if(this.dialog){this.logger.log("Additional confirmed dialog, sending ACK and BYE"),this.ackAndBye(t);return}if(this.isCanceled){this.logger.log("Canceled session accepted, sending ACK and BYE"),this.ackAndBye(t),this.stateTransition(m.Terminated);return}this.notifyReferer(t),this.onAccept(t).then(()=>{this.disposeEarlyMedia()}).catch(()=>{this.disposeEarlyMedia()}).then(()=>{e.requestDelegate&&e.requestDelegate.onAccept&&e.requestDelegate.onAccept(t)})},onProgress:t=>{this.isCanceled||(this.notifyReferer(t),this.onProgress(t).catch(()=>{this.disposeEarlyMedia()}).then(()=>{e.requestDelegate&&e.requestDelegate.onProgress&&e.requestDelegate.onProgress(t)}))},onRedirect:t=>{this.notifyReferer(t),this.onRedirect(t),e.requestDelegate&&e.requestDelegate.onRedirect&&e.requestDelegate.onRedirect(t)},onReject:t=>{this.notifyReferer(t),this.onReject(t),e.requestDelegate&&e.requestDelegate.onReject&&e.requestDelegate.onReject(t)},onTrying:t=>{this.notifyReferer(t),this.onTrying(t),e.requestDelegate&&e.requestDelegate.onTrying&&e.requestDelegate.onTrying(t)}}),this.outgoingInviteRequest}disposeEarlyMedia(){this.earlyMediaSessionDescriptionHandlers.forEach(e=>{e.close()}),this.earlyMediaSessionDescriptionHandlers.clear()}notifyReferer(e){if(!this._referred)return;if(!(this._referred instanceof me))throw new Error("Referred session not instance of session");if(!this._referred.dialog)return;if(!e.message.statusCode)throw new Error("Status code undefined.");if(!e.message.reasonPhrase)throw new Error("Reason phrase undefined.");const t=e.message.statusCode,i=e.message.reasonPhrase,s=`SIP/2.0 ${t} ${i}`.trim(),r=this._referred.dialog.notify(void 0,{extraHeaders:["Event: refer","Subscription-State: terminated"],body:{contentDisposition:"render",contentType:"message/sipfrag",content:s}});r.delegate={onReject:()=>{this._referred=void 0}}}onAccept(e){if(this.logger.log("Inviter.onAccept"),this.state!==m.Establishing)return this.logger.error(`Accept received while in state ${this.state}, dropping response`),Promise.reject(new Error(`Invalid session state ${this.state}`));const t=e.message,i=e.session;switch(t.hasHeader("P-Asserted-Identity")&&(this._assertedIdentity=k.nameAddrHeaderParse(t.getHeader("P-Asserted-Identity"))),i.delegate={onAck:s=>this.onAckRequest(s),onBye:s=>this.onByeRequest(s),onInfo:s=>this.onInfoRequest(s),onInvite:s=>this.onInviteRequest(s),onMessage:s=>this.onMessageRequest(s),onNotify:s=>this.onNotifyRequest(s),onPrack:s=>this.onPrackRequest(s),onRefer:s=>this.onReferRequest(s)},this._dialog=i,i.signalingState){case b.Initial:return this.logger.error("Received 2xx response to INVITE without a session description"),this.ackAndBye(e,400,"Missing session description"),this.stateTransition(m.Terminated),Promise.reject(new Error("Bad Media Description"));case b.HaveLocalOffer:return this.logger.error("Received 2xx response to INVITE without a session description"),this.ackAndBye(e,400,"Missing session description"),this.stateTransition(m.Terminated),Promise.reject(new Error("Bad Media Description"));case b.HaveRemoteOffer:{if(!this._dialog.offer)throw new Error(`Session offer undefined in signaling state ${this._dialog.signalingState}.`);const s={sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiers,sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptions};return this.setOfferAndGetAnswer(this._dialog.offer,s).then(r=>{e.ack({body:r}),this.stateTransition(m.Established)}).catch(r=>{throw this.ackAndBye(e,488,"Invalid session description"),this.stateTransition(m.Terminated),r})}case b.Stable:{if(this.earlyMediaSessionDescriptionHandlers.size>0){const n=this.earlyMediaSessionDescriptionHandlers.get(i.id);if(!n)throw new Error("Session description handler undefined.");return this.setSessionDescriptionHandler(n),this.earlyMediaSessionDescriptionHandlers.delete(i.id),e.ack(),this.stateTransition(m.Established),Promise.resolve()}if(this.earlyMediaDialog){if(this.earlyMediaDialog!==i){this.earlyMedia&&this.logger.error("You have set the 'earlyMedia' option to 'true' which requires that your INVITE requests do not fork and yet this INVITE request did in fact fork. Consequentially and not surprisingly the end point which accepted the INVITE (confirmed dialog) does not match the end point with which early media has been setup (early dialog) and thus this session is unable to proceed. In accordance with the SIP specifications, the SIP servers your end point is connected to determine if an INVITE forks and the forking behavior of those servers cannot be controlled by this library. If you wish to use early media with this library you must configure those servers accordingly. Alternatively you may set the 'earlyMedia' to 'false' which will allow this library to function with any INVITE requests which do fork.");const n=new Error("Early media dialog does not equal confirmed dialog, terminating session");return this.logger.error(n.message),this.ackAndBye(e,488,"Not Acceptable Here"),this.stateTransition(m.Terminated),Promise.reject(n)}return e.ack(),this.stateTransition(m.Established),Promise.resolve()}const s=i.answer;if(!s)throw new Error("Answer is undefined.");const r={sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiers,sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptions};return this.setAnswer(s,r).then(()=>{let n;this._renderbody&&this._rendertype&&(n={body:{contentDisposition:"render",contentType:this._rendertype,content:this._renderbody}}),e.ack(n),this.stateTransition(m.Established)}).catch(n=>{throw this.logger.error(n.message),this.ackAndBye(e,488,"Not Acceptable Here"),this.stateTransition(m.Terminated),n})}case b.Closed:return Promise.reject(new Error("Terminated."));default:throw new Error("Unknown session signaling state.")}}onProgress(e){var t;if(this.logger.log("Inviter.onProgress"),this.state!==m.Establishing)return this.logger.error(`Progress received while in state ${this.state}, dropping response`),Promise.reject(new Error(`Invalid session state ${this.state}`));if(!this.outgoingInviteRequest)throw new Error("Outgoing INVITE request undefined.");const i=e.message,s=e.session;i.hasHeader("P-Asserted-Identity")&&(this._assertedIdentity=k.nameAddrHeaderParse(i.getHeader("P-Asserted-Identity")));const r=i.getHeader("require"),n=i.getHeader("rseq"),d=!!(r&&r.includes("100rel")&&n?Number(n):void 0),f=[];switch(d&&f.push("RAck: "+i.getHeader("rseq")+" "+i.getHeader("cseq")),s.signalingState){case b.Initial:return d&&(this.logger.warn("First reliable provisional response received MUST contain an offer when INVITE does not contain an offer."),e.prack({extraHeaders:f})),Promise.resolve();case b.HaveLocalOffer:return d&&e.prack({extraHeaders:f}),Promise.resolve();case b.HaveRemoteOffer:if(!d)return this.logger.warn("Non-reliable provisional response MUST NOT contain an initial offer, discarding response."),Promise.resolve();{const h=this.sessionDescriptionHandlerFactory(this,this.userAgent.configuration.sessionDescriptionHandlerFactoryOptions||{});return!((t=this.delegate)===null||t===void 0)&&t.onSessionDescriptionHandler&&this.delegate.onSessionDescriptionHandler(h,!0),this.earlyMediaSessionDescriptionHandlers.set(s.id,h),h.setDescription(i.body,this.sessionDescriptionHandlerOptions,this.sessionDescriptionHandlerModifiers).then(()=>h.getDescription(this.sessionDescriptionHandlerOptions,this.sessionDescriptionHandlerModifiers)).then(w=>{const S={contentDisposition:"session",contentType:w.contentType,content:w.body};e.prack({extraHeaders:f,body:S})}).catch(w=>{throw this.stateTransition(m.Terminated),w})}case b.Stable:if(d&&e.prack({extraHeaders:f}),this.earlyMedia&&!this.earlyMediaDialog){this.earlyMediaDialog=s;const h=s.answer;if(!h)throw new Error("Answer is undefined.");const w={sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiers,sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptions};return this.setAnswer(h,w).catch(S=>{throw this.stateTransition(m.Terminated),S})}return Promise.resolve();case b.Closed:return Promise.reject(new Error("Terminated."));default:throw new Error("Unknown session signaling state.")}}onRedirect(e){if(this.logger.log("Inviter.onRedirect"),this.state!==m.Establishing&&this.state!==m.Terminating){this.logger.error(`Redirect received while in state ${this.state}, dropping response`);return}this.stateTransition(m.Terminated)}onReject(e){if(this.logger.log("Inviter.onReject"),this.state!==m.Establishing&&this.state!==m.Terminating){this.logger.error(`Reject received while in state ${this.state}, dropping response`);return}this.stateTransition(m.Terminated)}onTrying(e){if(this.logger.log("Inviter.onTrying"),this.state!==m.Establishing){this.logger.error(`Trying received while in state ${this.state}, dropping response`);return}}}class jt{constructor(e,t,i,s="text/plain",r={}){this.logger=e.getLogger("sip.Messager"),r.params=r.params||{};let n=e.userAgentCore.configuration.aor;if(r.params.fromUri&&(n=typeof r.params.fromUri=="string"?k.URIParse(r.params.fromUri):r.params.fromUri),!n)throw new TypeError("Invalid from URI: "+r.params.fromUri);let a=t;if(r.params.toUri&&(a=typeof r.params.toUri=="string"?k.URIParse(r.params.toUri):r.params.toUri),!a)throw new TypeError("Invalid to URI: "+r.params.toUri);const d=r.params?Object.assign({},r.params):{},f=(r.extraHeaders||[]).slice(),w={contentDisposition:"render",contentType:s,content:i};this.request=e.userAgentCore.makeOutgoingRequestMessage(v.MESSAGE,t,n,a,d,f,w),this.userAgent=e}message(e={}){return this.userAgent.userAgentCore.request(this.request,e.requestDelegate),Promise.resolve()}}var _;(function(o){o.Initial="Initial",o.Registered="Registered",o.Unregistered="Unregistered",o.Terminated="Terminated"})(_=_||(_={}));class J{constructor(e,t={}){this.disposed=!1,this._contacts=[],this._retryAfter=void 0,this._state=_.Initial,this._waiting=!1,this._stateEventEmitter=new Se,this._waitingEventEmitter=new Se,this.userAgent=e;const i=e.configuration.uri.clone();if(i.user=void 0,this.options=Object.assign(Object.assign(Object.assign({},J.defaultOptions()),{registrar:i}),J.stripUndefinedProperties(t)),this.options.extraContactHeaderParams=(this.options.extraContactHeaderParams||[]).slice(),this.options.extraHeaders=(this.options.extraHeaders||[]).slice(),!this.options.registrar)throw new Error("Registrar undefined.");if(this.options.registrar=this.options.registrar.clone(),this.options.regId&&!this.options.instanceId?this.options.instanceId=this.userAgent.instanceId:!this.options.regId&&this.options.instanceId&&(this.options.regId=1),this.options.instanceId&&k.parse(this.options.instanceId,"uuid")===-1)throw new Error("Invalid instanceId.");if(this.options.regId&&this.options.regId<0)throw new Error("Invalid regId.");const s=this.options.registrar,r=this.options.params&&this.options.params.fromUri||e.userAgentCore.configuration.aor,n=this.options.params&&this.options.params.toUri||e.configuration.uri,a=this.options.params||{},d=(t.extraHeaders||[]).slice();if(this.request=e.userAgentCore.makeOutgoingRequestMessage(v.REGISTER,s,r,n,a,d,void 0),this.expires=this.options.expires||J.defaultExpires,this.expires<0)throw new Error("Invalid expires.");if(this.refreshFrequency=this.options.refreshFrequency||J.defaultRefreshFrequency,this.refreshFrequency<50||this.refreshFrequency>99)throw new Error("Invalid refresh frequency. The value represents a percentage of the expiration time and should be between 50 and 99.");this.logger=e.getLogger("sip.Registerer"),this.options.logConfiguration&&(this.logger.log("Configuration:"),Object.keys(this.options).forEach(f=>{const h=this.options[f];f==="registrar"?this.logger.log("· "+f+": "+h):this.logger.log("· "+f+": "+JSON.stringify(h))})),this.id=this.request.callId+this.request.from.parameters.tag,this.userAgent._registerers[this.id]=this}static defaultOptions(){return{expires:J.defaultExpires,extraContactHeaderParams:[],extraHeaders:[],logConfiguration:!0,instanceId:"",params:{},regId:0,registrar:new z("sip","anonymous","anonymous.invalid"),refreshFrequency:J.defaultRefreshFrequency}}static stripUndefinedProperties(e){return Object.keys(e).reduce((t,i)=>(e[i]!==void 0&&(t[i]=e[i]),t),{})}get contacts(){return this._contacts.slice()}get retryAfter(){return this._retryAfter}get state(){return this._state}get stateChange(){return this._stateEventEmitter}dispose(){return this.disposed?Promise.resolve():(this.disposed=!0,this.logger.log(`Registerer ${this.id} in state ${this.state} is being disposed`),delete this.userAgent._registerers[this.id],new Promise(e=>{const t=()=>{if(!this.waiting&&this._state===_.Registered){this.stateChange.addListener(()=>{this.terminated(),e()},{once:!0}),this.unregister();return}this.terminated(),e()};this.waiting?this.waitingChange.addListener(()=>{t()},{once:!0}):t()}))}register(e={}){if(this.state===_.Terminated)throw this.stateError(),new Error("Registerer terminated. Unable to register.");if(this.disposed)throw this.stateError(),new Error("Registerer disposed. Unable to register.");if(this.waiting){this.waitingWarning();const s=new be("REGISTER request already in progress, waiting for final response");return Promise.reject(s)}e.requestOptions&&(this.options=Object.assign(Object.assign({},this.options),e.requestOptions));const t=(this.options.extraHeaders||[]).slice();t.push("Contact: "+this.generateContactHeader(this.expires)),t.push("Allow: "+["ACK","CANCEL","INVITE","MESSAGE","BYE","OPTIONS","INFO","NOTIFY","REFER"].toString()),this.request.cseq++,this.request.setHeader("cseq",this.request.cseq+" REGISTER"),this.request.extraHeaders=t,this.waitingToggle(!0);const i=this.userAgent.userAgentCore.register(this.request,{onAccept:s=>{let r;s.message.hasHeader("expires")&&(r=Number(s.message.getHeader("expires"))),this._contacts=s.message.getHeaders("contact");let n=this._contacts.length;if(!n){this.logger.error("No Contact header in response to REGISTER, dropping response."),this.unregistered();return}let a;for(;n--;){if(a=s.message.parseHeader("contact",n),!a)throw new Error("Contact undefined");if(this.userAgent.contact.pubGruu&&it(a.uri,this.userAgent.contact.pubGruu)){r=Number(a.getParam("expires"));break}if(this.userAgent.configuration.contactName===""){if(a.uri.user===this.userAgent.contact.uri.user){r=Number(a.getParam("expires"));break}}else if(it(a.uri,this.userAgent.contact.uri)){r=Number(a.getParam("expires"));break}a=void 0}if(a===void 0){this.logger.error("No Contact header pointing to us, dropping response"),this.unregistered(),this.waitingToggle(!1);return}if(r===void 0){this.logger.error("Contact pointing to us is missing expires parameter, dropping response"),this.unregistered(),this.waitingToggle(!1);return}if(a.hasParam("temp-gruu")){const d=a.getParam("temp-gruu");d&&(this.userAgent.contact.tempGruu=k.URIParse(d.replace(/"/g,"")))}if(a.hasParam("pub-gruu")){const d=a.getParam("pub-gruu");d&&(this.userAgent.contact.pubGruu=k.URIParse(d.replace(/"/g,"")))}this.registered(r),e.requestDelegate&&e.requestDelegate.onAccept&&e.requestDelegate.onAccept(s),this.waitingToggle(!1)},onProgress:s=>{e.requestDelegate&&e.requestDelegate.onProgress&&e.requestDelegate.onProgress(s)},onRedirect:s=>{this.logger.error("Redirect received. Not supported."),this.unregistered(),e.requestDelegate&&e.requestDelegate.onRedirect&&e.requestDelegate.onRedirect(s),this.waitingToggle(!1)},onReject:s=>{if(s.message.statusCode===423){if(!s.message.hasHeader("min-expires")){this.logger.error("423 response received for REGISTER without Min-Expires, dropping response"),this.unregistered(),this.waitingToggle(!1);return}this.expires=Number(s.message.getHeader("min-expires")),this.waitingToggle(!1),this.register();return}this.logger.warn(`Failed to register, status code ${s.message.statusCode}`);let r=NaN;if(s.message.statusCode===500||s.message.statusCode===503){const n=s.message.getHeader("retry-after");n&&(r=Number.parseInt(n,void 0))}this._retryAfter=isNaN(r)?void 0:r,this.unregistered(),e.requestDelegate&&e.requestDelegate.onReject&&e.requestDelegate.onReject(s),this._retryAfter=void 0,this.waitingToggle(!1)},onTrying:s=>{e.requestDelegate&&e.requestDelegate.onTrying&&e.requestDelegate.onTrying(s)}});return Promise.resolve(i)}unregister(e={}){if(this.state===_.Terminated)throw this.stateError(),new Error("Registerer terminated. Unable to register.");if(this.disposed&&this.state!==_.Registered)throw this.stateError(),new Error("Registerer disposed. Unable to register.");if(this.waiting){this.waitingWarning();const s=new be("REGISTER request already in progress, waiting for final response");return Promise.reject(s)}this._state!==_.Registered&&!e.all&&this.logger.warn("Not currently registered, but sending an unregister anyway.");const t=(e.requestOptions&&e.requestOptions.extraHeaders||[]).slice();this.request.extraHeaders=t,e.all?(t.push("Contact: *"),t.push("Expires: 0")):t.push("Contact: "+this.generateContactHeader(0)),this.request.cseq++,this.request.setHeader("cseq",this.request.cseq+" REGISTER"),this.registrationTimer!==void 0&&(clearTimeout(this.registrationTimer),this.registrationTimer=void 0),this.waitingToggle(!0);const i=this.userAgent.userAgentCore.register(this.request,{onAccept:s=>{this._contacts=s.message.getHeaders("contact"),this.unregistered(),e.requestDelegate&&e.requestDelegate.onAccept&&e.requestDelegate.onAccept(s),this.waitingToggle(!1)},onProgress:s=>{e.requestDelegate&&e.requestDelegate.onProgress&&e.requestDelegate.onProgress(s)},onRedirect:s=>{this.logger.error("Unregister redirected. Not currently supported."),this.unregistered(),e.requestDelegate&&e.requestDelegate.onRedirect&&e.requestDelegate.onRedirect(s),this.waitingToggle(!1)},onReject:s=>{this.logger.error(`Unregister rejected with status code ${s.message.statusCode}`),this.unregistered(),e.requestDelegate&&e.requestDelegate.onReject&&e.requestDelegate.onReject(s),this.waitingToggle(!1)},onTrying:s=>{e.requestDelegate&&e.requestDelegate.onTrying&&e.requestDelegate.onTrying(s)}});return Promise.resolve(i)}clearTimers(){this.registrationTimer!==void 0&&(clearTimeout(this.registrationTimer),this.registrationTimer=void 0),this.registrationExpiredTimer!==void 0&&(clearTimeout(this.registrationExpiredTimer),this.registrationExpiredTimer=void 0)}generateContactHeader(e){let t=this.userAgent.contact.toString({register:!0});return this.options.regId&&this.options.instanceId&&(t+=";reg-id="+this.options.regId,t+=';+sip.instance="<urn:uuid:'+this.options.instanceId+'>"'),this.options.extraContactHeaderParams&&this.options.extraContactHeaderParams.forEach(i=>{t+=";"+i}),t+=";expires="+e,t}registered(e){this.clearTimers(),this.registrationTimer=setTimeout(()=>{this.registrationTimer=void 0,this.register()},this.refreshFrequency/100*e*1e3),this.registrationExpiredTimer=setTimeout(()=>{this.logger.warn("Registration expired"),this.unregistered()},e*1e3),this._state!==_.Registered&&this.stateTransition(_.Registered)}unregistered(){this.clearTimers(),this._state!==_.Unregistered&&this.stateTransition(_.Unregistered)}terminated(){this.clearTimers(),this._state!==_.Terminated&&this.stateTransition(_.Terminated)}stateTransition(e){const t=()=>{throw new Error(`Invalid state transition from ${this._state} to ${e}`)};switch(this._state){case _.Initial:e!==_.Registered&&e!==_.Unregistered&&e!==_.Terminated&&t();break;case _.Registered:e!==_.Unregistered&&e!==_.Terminated&&t();break;case _.Unregistered:e!==_.Registered&&e!==_.Terminated&&t();break;case _.Terminated:t();break;default:throw new Error("Unrecognized state.")}this._state=e,this.logger.log(`Registration transitioned to state ${this._state}`),this._stateEventEmitter.emit(this._state),e===_.Terminated&&this.dispose()}get waiting(){return this._waiting}get waitingChange(){return this._waitingEventEmitter}waitingToggle(e){if(this._waiting===e)throw new Error(`Invalid waiting transition from ${this._waiting} to ${e}`);this._waiting=e,this.logger.log(`Waiting toggled to ${this._waiting}`),this._waitingEventEmitter.emit(this._waiting)}waitingWarning(){let e="An attempt was made to send a REGISTER request while a prior one was still in progress.";e+=" RFC 3261 requires UAs MUST NOT send a new registration until they have received a final response",e+=" from the registrar for the previous one or the previous REGISTER request has timed out.",e+=" Note that if the transport disconnects, you still must wait for the prior request to time out before",e+=" sending a new REGISTER request or alternatively dispose of the current Registerer and create a new Registerer.",this.logger.warn(e)}stateError(){let t=`An attempt was made to send a REGISTER request when the Registerer ${this.state===_.Terminated?"is in 'Terminated' state":"has been disposed"}.`;t+=" The Registerer transitions to 'Terminated' when Registerer.dispose() is called.",t+=" Perhaps you called UserAgent.stop() which dipsoses of all Registerers?",this.logger.error(t)}}J.defaultExpires=600,J.defaultRefreshFrequency=99;var R;(function(o){o.Initial="Initial",o.NotifyWait="NotifyWait",o.Pending="Pending",o.Active="Active",o.Terminated="Terminated"})(R=R||(R={}));var T;(function(o){o.Connecting="Connecting",o.Connected="Connected",o.Disconnecting="Disconnecting",o.Disconnected="Disconnected"})(T=T||(T={}));var P;(function(o){o.Started="Started",o.Stopped="Stopped"})(P=P||(P={}));class H{constructor(){this._dataLength=0,this._bufferLength=0,this._state=new Int32Array(4),this._buffer=new ArrayBuffer(68),this._buffer8=new Uint8Array(this._buffer,0,68),this._buffer32=new Uint32Array(this._buffer,0,17),this.start()}static hashStr(e,t=!1){return this.onePassHasher.start().appendStr(e).end(t)}static hashAsciiStr(e,t=!1){return this.onePassHasher.start().appendAsciiStr(e).end(t)}static _hex(e){const t=H.hexChars,i=H.hexOut;let s,r,n,a;for(a=0;a<4;a+=1)for(r=a*8,s=e[a],n=0;n<8;n+=2)i[r+1+n]=t.charAt(s&15),s>>>=4,i[r+0+n]=t.charAt(s&15),s>>>=4;return i.join("")}static _md5cycle(e,t){let i=e[0],s=e[1],r=e[2],n=e[3];i+=(s&r|~s&n)+t[0]-680876936|0,i=(i<<7|i>>>25)+s|0,n+=(i&s|~i&r)+t[1]-389564586|0,n=(n<<12|n>>>20)+i|0,r+=(n&i|~n&s)+t[2]+606105819|0,r=(r<<17|r>>>15)+n|0,s+=(r&n|~r&i)+t[3]-1044525330|0,s=(s<<22|s>>>10)+r|0,i+=(s&r|~s&n)+t[4]-176418897|0,i=(i<<7|i>>>25)+s|0,n+=(i&s|~i&r)+t[5]+1200080426|0,n=(n<<12|n>>>20)+i|0,r+=(n&i|~n&s)+t[6]-1473231341|0,r=(r<<17|r>>>15)+n|0,s+=(r&n|~r&i)+t[7]-45705983|0,s=(s<<22|s>>>10)+r|0,i+=(s&r|~s&n)+t[8]+1770035416|0,i=(i<<7|i>>>25)+s|0,n+=(i&s|~i&r)+t[9]-1958414417|0,n=(n<<12|n>>>20)+i|0,r+=(n&i|~n&s)+t[10]-42063|0,r=(r<<17|r>>>15)+n|0,s+=(r&n|~r&i)+t[11]-1990404162|0,s=(s<<22|s>>>10)+r|0,i+=(s&r|~s&n)+t[12]+1804603682|0,i=(i<<7|i>>>25)+s|0,n+=(i&s|~i&r)+t[13]-40341101|0,n=(n<<12|n>>>20)+i|0,r+=(n&i|~n&s)+t[14]-1502002290|0,r=(r<<17|r>>>15)+n|0,s+=(r&n|~r&i)+t[15]+1236535329|0,s=(s<<22|s>>>10)+r|0,i+=(s&n|r&~n)+t[1]-165796510|0,i=(i<<5|i>>>27)+s|0,n+=(i&r|s&~r)+t[6]-1069501632|0,n=(n<<9|n>>>23)+i|0,r+=(n&s|i&~s)+t[11]+643717713|0,r=(r<<14|r>>>18)+n|0,s+=(r&i|n&~i)+t[0]-373897302|0,s=(s<<20|s>>>12)+r|0,i+=(s&n|r&~n)+t[5]-701558691|0,i=(i<<5|i>>>27)+s|0,n+=(i&r|s&~r)+t[10]+38016083|0,n=(n<<9|n>>>23)+i|0,r+=(n&s|i&~s)+t[15]-660478335|0,r=(r<<14|r>>>18)+n|0,s+=(r&i|n&~i)+t[4]-405537848|0,s=(s<<20|s>>>12)+r|0,i+=(s&n|r&~n)+t[9]+568446438|0,i=(i<<5|i>>>27)+s|0,n+=(i&r|s&~r)+t[14]-1019803690|0,n=(n<<9|n>>>23)+i|0,r+=(n&s|i&~s)+t[3]-187363961|0,r=(r<<14|r>>>18)+n|0,s+=(r&i|n&~i)+t[8]+1163531501|0,s=(s<<20|s>>>12)+r|0,i+=(s&n|r&~n)+t[13]-1444681467|0,i=(i<<5|i>>>27)+s|0,n+=(i&r|s&~r)+t[2]-51403784|0,n=(n<<9|n>>>23)+i|0,r+=(n&s|i&~s)+t[7]+1735328473|0,r=(r<<14|r>>>18)+n|0,s+=(r&i|n&~i)+t[12]-1926607734|0,s=(s<<20|s>>>12)+r|0,i+=(s^r^n)+t[5]-378558|0,i=(i<<4|i>>>28)+s|0,n+=(i^s^r)+t[8]-2022574463|0,n=(n<<11|n>>>21)+i|0,r+=(n^i^s)+t[11]+1839030562|0,r=(r<<16|r>>>16)+n|0,s+=(r^n^i)+t[14]-35309556|0,s=(s<<23|s>>>9)+r|0,i+=(s^r^n)+t[1]-1530992060|0,i=(i<<4|i>>>28)+s|0,n+=(i^s^r)+t[4]+1272893353|0,n=(n<<11|n>>>21)+i|0,r+=(n^i^s)+t[7]-155497632|0,r=(r<<16|r>>>16)+n|0,s+=(r^n^i)+t[10]-1094730640|0,s=(s<<23|s>>>9)+r|0,i+=(s^r^n)+t[13]+681279174|0,i=(i<<4|i>>>28)+s|0,n+=(i^s^r)+t[0]-358537222|0,n=(n<<11|n>>>21)+i|0,r+=(n^i^s)+t[3]-722521979|0,r=(r<<16|r>>>16)+n|0,s+=(r^n^i)+t[6]+76029189|0,s=(s<<23|s>>>9)+r|0,i+=(s^r^n)+t[9]-640364487|0,i=(i<<4|i>>>28)+s|0,n+=(i^s^r)+t[12]-421815835|0,n=(n<<11|n>>>21)+i|0,r+=(n^i^s)+t[15]+530742520|0,r=(r<<16|r>>>16)+n|0,s+=(r^n^i)+t[2]-995338651|0,s=(s<<23|s>>>9)+r|0,i+=(r^(s|~n))+t[0]-198630844|0,i=(i<<6|i>>>26)+s|0,n+=(s^(i|~r))+t[7]+1126891415|0,n=(n<<10|n>>>22)+i|0,r+=(i^(n|~s))+t[14]-1416354905|0,r=(r<<15|r>>>17)+n|0,s+=(n^(r|~i))+t[5]-57434055|0,s=(s<<21|s>>>11)+r|0,i+=(r^(s|~n))+t[12]+1700485571|0,i=(i<<6|i>>>26)+s|0,n+=(s^(i|~r))+t[3]-1894986606|0,n=(n<<10|n>>>22)+i|0,r+=(i^(n|~s))+t[10]-1051523|0,r=(r<<15|r>>>17)+n|0,s+=(n^(r|~i))+t[1]-2054922799|0,s=(s<<21|s>>>11)+r|0,i+=(r^(s|~n))+t[8]+1873313359|0,i=(i<<6|i>>>26)+s|0,n+=(s^(i|~r))+t[15]-30611744|0,n=(n<<10|n>>>22)+i|0,r+=(i^(n|~s))+t[6]-1560198380|0,r=(r<<15|r>>>17)+n|0,s+=(n^(r|~i))+t[13]+1309151649|0,s=(s<<21|s>>>11)+r|0,i+=(r^(s|~n))+t[4]-145523070|0,i=(i<<6|i>>>26)+s|0,n+=(s^(i|~r))+t[11]-1120210379|0,n=(n<<10|n>>>22)+i|0,r+=(i^(n|~s))+t[2]+718787259|0,r=(r<<15|r>>>17)+n|0,s+=(n^(r|~i))+t[9]-343485551|0,s=(s<<21|s>>>11)+r|0,e[0]=i+e[0]|0,e[1]=s+e[1]|0,e[2]=r+e[2]|0,e[3]=n+e[3]|0}start(){return this._dataLength=0,this._bufferLength=0,this._state.set(H.stateIdentity),this}appendStr(e){const t=this._buffer8,i=this._buffer32;let s=this._bufferLength,r,n;for(n=0;n<e.length;n+=1){if(r=e.charCodeAt(n),r<128)t[s++]=r;else if(r<2048)t[s++]=(r>>>6)+192,t[s++]=r&63|128;else if(r<55296||r>56319)t[s++]=(r>>>12)+224,t[s++]=r>>>6&63|128,t[s++]=r&63|128;else{if(r=(r-55296)*1024+(e.charCodeAt(++n)-56320)+65536,r>1114111)throw new Error("Unicode standard supports code points up to U+10FFFF");t[s++]=(r>>>18)+240,t[s++]=r>>>12&63|128,t[s++]=r>>>6&63|128,t[s++]=r&63|128}s>=64&&(this._dataLength+=64,H._md5cycle(this._state,i),s-=64,i[0]=i[16])}return this._bufferLength=s,this}appendAsciiStr(e){const t=this._buffer8,i=this._buffer32;let s=this._bufferLength,r,n=0;for(;;){for(r=Math.min(e.length-n,64-s);r--;)t[s++]=e.charCodeAt(n++);if(s<64)break;this._dataLength+=64,H._md5cycle(this._state,i),s=0}return this._bufferLength=s,this}appendByteArray(e){const t=this._buffer8,i=this._buffer32;let s=this._bufferLength,r,n=0;for(;;){for(r=Math.min(e.length-n,64-s);r--;)t[s++]=e[n++];if(s<64)break;this._dataLength+=64,H._md5cycle(this._state,i),s=0}return this._bufferLength=s,this}getState(){const e=this,t=e._state;return{buffer:String.fromCharCode.apply(null,e._buffer8),buflen:e._bufferLength,length:e._dataLength,state:[t[0],t[1],t[2],t[3]]}}setState(e){const t=e.buffer,i=e.state,s=this._state;let r;for(this._dataLength=e.length,this._bufferLength=e.buflen,s[0]=i[0],s[1]=i[1],s[2]=i[2],s[3]=i[3],r=0;r<t.length;r+=1)this._buffer8[r]=t.charCodeAt(r)}end(e=!1){const t=this._bufferLength,i=this._buffer8,s=this._buffer32,r=(t>>2)+1;let n;if(this._dataLength+=t,i[t]=128,i[t+1]=i[t+2]=i[t+3]=0,s.set(H.buffer32Identity.subarray(r),r),t>55&&(H._md5cycle(this._state,s),s.set(H.buffer32Identity)),n=this._dataLength*8,n<=4294967295)s[14]=n;else{const a=n.toString(16).match(/(.*?)(.{0,8})$/);if(a===null)return;const d=parseInt(a[2],16),f=parseInt(a[1],16)||0;s[14]=d,s[15]=f}return H._md5cycle(this._state,s),e?this._state:H._hex(this._state)}}H.stateIdentity=new Int32Array([1732584193,-271733879,-1732584194,271733878]),H.buffer32Identity=new Int32Array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),H.hexChars="0123456789abcdef",H.hexOut=[],H.onePassHasher=new H,H.hashStr("hello")!=="5d41402abc4b2a76b9719d911017c592"&&console.error("Md5 self test failed.");function oe(o){return H.hashStr(o)}class Vt{constructor(e,t,i,s){this.logger=e.getLogger("sipjs.digestauthentication"),this.username=i,this.password=s,this.ha1=t,this.nc=0,this.ncHex="00000000"}authenticate(e,t,i){if(this.algorithm=t.algorithm,this.realm=t.realm,this.nonce=t.nonce,this.opaque=t.opaque,this.stale=t.stale,this.algorithm){if(this.algorithm!=="MD5")return this.logger.warn("challenge with Digest algorithm different than 'MD5', authentication aborted"),!1}else this.algorithm="MD5";if(!this.realm)return this.logger.warn("challenge without Digest realm, authentication aborted"),!1;if(!this.nonce)return this.logger.warn("challenge without Digest nonce, authentication aborted"),!1;if(t.qop)if(t.qop.indexOf("auth")>-1)this.qop="auth";else if(t.qop.indexOf("auth-int")>-1)this.qop="auth-int";else return this.logger.warn("challenge without Digest qop different than 'auth' or 'auth-int', authentication aborted"),!1;else this.qop=void 0;return this.method=e.method,this.uri=e.ruri,this.cnonce=le(12),this.nc+=1,this.updateNcHex(),this.nc===4294967296&&(this.nc=1,this.ncHex="00000001"),this.calculateResponse(i),!0}toString(){const e=[];if(!this.response)throw new Error("response field does not exist, cannot generate Authorization header");return e.push("algorithm="+this.algorithm),e.push('username="'+this.username+'"'),e.push('realm="'+this.realm+'"'),e.push('nonce="'+this.nonce+'"'),e.push('uri="'+this.uri+'"'),e.push('response="'+this.response+'"'),this.opaque&&e.push('opaque="'+this.opaque+'"'),this.qop&&(e.push("qop="+this.qop),e.push('cnonce="'+this.cnonce+'"'),e.push("nc="+this.ncHex)),"Digest "+e.join(", ")}updateNcHex(){const e=Number(this.nc).toString(16);this.ncHex="00000000".substr(0,8-e.length)+e}calculateResponse(e){let t,i;t=this.ha1,(t===""||t===void 0)&&(t=oe(this.username+":"+this.realm+":"+this.password)),this.qop==="auth"?(i=oe(this.method+":"+this.uri),this.response=oe(t+":"+this.nonce+":"+this.ncHex+":"+this.cnonce+":auth:"+i)):this.qop==="auth-int"?(i=oe(this.method+":"+this.uri+":"+oe(e||"")),this.response=oe(t+":"+this.nonce+":"+this.ncHex+":"+this.cnonce+":auth-int:"+i)):this.qop===void 0&&(i=oe(this.method+":"+this.uri),this.response=oe(t+":"+this.nonce+":"+i))}}var q;(function(o){o[o.error=0]="error",o[o.warn=1]="warn",o[o.log=2]="log",o[o.debug=3]="debug"})(q=q||(q={}));class ct{constructor(e,t,i){this.logger=e,this.category=t,this.label=i}error(e){this.genericLog(q.error,e)}warn(e){this.genericLog(q.warn,e)}log(e){this.genericLog(q.log,e)}debug(e){this.genericLog(q.debug,e)}genericLog(e,t){this.logger.genericLog(e,this.category,this.label,t)}get level(){return this.logger.level}set level(e){this.logger.level=e}}class Gt{constructor(){this.builtinEnabled=!0,this._level=q.log,this.loggers={},this.logger=this.getLogger("sip:loggerfactory")}get level(){return this._level}set level(e){e>=0&&e<=3?this._level=e:e>3?this._level=3:q.hasOwnProperty(e)?this._level=e:this.logger.error("invalid 'level' parameter value: "+JSON.stringify(e))}get connector(){return this._connector}set connector(e){e?typeof e=="function"?this._connector=e:this.logger.error("invalid 'connector' parameter value: "+JSON.stringify(e)):this._connector=void 0}getLogger(e,t){if(t&&this.level===3)return new ct(this,e,t);if(this.loggers[e])return this.loggers[e];{const i=new ct(this,e);return this.loggers[e]=i,i}}genericLog(e,t,i,s){this.level>=e&&this.builtinEnabled&&this.print(e,t,i,s),this.connector&&this.connector(q[e],t,i,s)}print(e,t,i,s){if(typeof s=="string"){const r=[new Date,t];i&&r.push(i),s=r.concat(s).join(" | ")}switch(e){case q.error:console.error(s);break;case q.warn:console.warn(s);break;case q.log:console.log(s);break;case q.debug:console.debug(s);break}}}var ke;(function(o){function e(s,r){let n=r,a=0,d=0;if(s.substring(n,n+2).match(/(^\r\n)/))return-2;for(;a===0;){if(d=s.indexOf(`\r
|
|
23
|
-
`,n),d===-1)return d;!s.substring(d+2,d+4).match(/(^\r\n)/)&&s.charAt(d+2).match(/(^\s+)/)?n=d+2:
|
|
24
|
-
`);if(
|
|
25
|
-
`;e.statusCode>=100&&e.statusCode<200,e.statusCode;const r="From: "+
|
|
26
|
-
`,n="Call-ID: "+
|
|
27
|
-
`,
|
|
28
|
-
`,d=
|
|
29
|
-
`,"");let
|
|
22
|
+
`,e}}function nt(a){return a==="application/sdp"?"session":"render"}function De(a){const e=typeof a=="string"?a:a.body,t=typeof a=="string"?"application/sdp":a.contentType;return{contentDisposition:nt(t),contentType:t,content:e}}function at(a){return a&&typeof a.content=="string"&&typeof a.contentType=="string"&&a.contentDisposition===void 0?!0:typeof a.contentDisposition=="string"}function Ee(a){let e,t,i;if(a instanceof me&&a.body){const s=a.parseHeader("Content-Disposition");e=s?s.type:void 0,t=a.parseHeader("Content-Type"),i=a.body}if(a instanceof re&&a.body){const s=a.parseHeader("Content-Disposition");e=s?s.type:void 0,t=a.parseHeader("Content-Type"),i=a.body}if(a instanceof ge&&a.body)if(e=a.getHeader("Content-Disposition"),t=a.getHeader("Content-Type"),typeof a.body=="string"){if(!t)throw new Error("Header content type header does not equal body content type.");i=a.body}else{if(t&&t!==a.body.contentType)throw new Error("Header content type header does not equal body content type.");t=a.body.contentType,i=a.body.body}if(at(a)&&(e=a.contentDisposition,t=a.contentType,i=a.content),!!i){if(t&&!e&&(e=nt(t)),!e)throw new Error("Content disposition undefined.");if(!t)throw new Error("Content type undefined.");return{contentDisposition:e,contentType:t,content:i}}}var V;(function(a){a.Initial="Initial",a.Early="Early",a.AckWait="AckWait",a.Confirmed="Confirmed",a.Terminated="Terminated"})(V=V||(V={}));var y;(function(a){a.Initial="Initial",a.HaveLocalOffer="HaveLocalOffer",a.HaveRemoteOffer="HaveRemoteOffer",a.Stable="Stable",a.Closed="Closed"})(y=y||(y={}));const te=500,Lt=4e3,ot=5e3,M={T1:te,T2:Lt,TIMER_B:64*te,TIMER_D:0*te,TIMER_F:64*te,TIMER_H:64*te,TIMER_I:0*ot,TIMER_J:0*te,TIMER_K:0*ot,TIMER_L:64*te,TIMER_M:64*te,TIMER_N:64*te,PROVISIONAL_RESPONSE_INTERVAL:6e4};class ne extends he{constructor(e){super(e||"Transaction state error.")}}var v;(function(a){a.ACK="ACK",a.BYE="BYE",a.CANCEL="CANCEL",a.INFO="INFO",a.INVITE="INVITE",a.MESSAGE="MESSAGE",a.NOTIFY="NOTIFY",a.OPTIONS="OPTIONS",a.REGISTER="REGISTER",a.UPDATE="UPDATE",a.SUBSCRIBE="SUBSCRIBE",a.PUBLISH="PUBLISH",a.REFER="REFER",a.PRACK="PRACK"})(v=v||(v={}));const ae=[v.ACK,v.BYE,v.CANCEL,v.INFO,v.INVITE,v.MESSAGE,v.NOTIFY,v.OPTIONS,v.PRACK,v.REFER,v.REGISTER,v.SUBSCRIBE];class ct{constructor(e){this.incomingMessageRequest=e}get request(){return this.incomingMessageRequest.message}accept(e){return this.incomingMessageRequest.accept(e),Promise.resolve()}reject(e){return this.incomingMessageRequest.reject(e),Promise.resolve()}}class Be{constructor(e){this.incomingNotifyRequest=e}get request(){return this.incomingNotifyRequest.message}accept(e){return this.incomingNotifyRequest.accept(e),Promise.resolve()}reject(e){return this.incomingNotifyRequest.reject(e),Promise.resolve()}}class Bt{constructor(e,t){this.incomingReferRequest=e,this.session=t}get referTo(){const e=this.incomingReferRequest.message.parseHeader("refer-to");if(!(e instanceof N))throw new Error("Failed to parse Refer-To header.");return e}get referredBy(){return this.incomingReferRequest.message.getHeader("referred-by")}get replaces(){const e=this.referTo.uri.getHeader("replaces");return e instanceof Array?e[0]:e}get request(){return this.incomingReferRequest.message}accept(e={statusCode:202}){return this.incomingReferRequest.accept(e),Promise.resolve()}reject(e){return this.incomingReferRequest.reject(e),Promise.resolve()}makeInviter(e){if(this.inviter)return this.inviter;const t=this.referTo.uri.clone();t.clearHeaders(),e=e||{};const i=(e.extraHeaders||[]).slice(),s=this.replaces;s&&i.push("Replaces: "+decodeURIComponent(s));const r=this.referredBy;return r&&i.push("Referred-By: "+r),e.extraHeaders=i,this.inviter=this.session.userAgent._makeInviter(t,e),this.inviter._referred=this.session,this.session._referral=this.inviter,this.inviter}}var w;(function(a){a.Initial="Initial",a.Establishing="Establishing",a.Established="Established",a.Terminating="Terminating",a.Terminated="Terminated"})(w=w||(w={}));class we{constructor(e,t={}){this.pendingReinvite=!1,this.pendingReinviteAck=!1,this._state=w.Initial,this.delegate=t.delegate,this._stateEventEmitter=new Te,this._userAgent=e}dispose(){switch(this.logger.log(`Session ${this.id} in state ${this._state} is being disposed`),delete this.userAgent._sessions[this.id],this._sessionDescriptionHandler&&this._sessionDescriptionHandler.close(),this.state){case w.Initial:break;case w.Establishing:break;case w.Established:return new Promise(e=>{this._bye({onAccept:()=>e(),onRedirect:()=>e(),onReject:()=>e()})});case w.Terminating:break;case w.Terminated:break;default:throw new Error("Unknown state.")}return Promise.resolve()}get assertedIdentity(){return this._assertedIdentity}get dialog(){return this._dialog}get id(){return this._id}get replacee(){return this._replacee}get sessionDescriptionHandler(){return this._sessionDescriptionHandler}get sessionDescriptionHandlerFactory(){return this.userAgent.configuration.sessionDescriptionHandlerFactory}get sessionDescriptionHandlerModifiers(){return this._sessionDescriptionHandlerModifiers||[]}set sessionDescriptionHandlerModifiers(e){this._sessionDescriptionHandlerModifiers=e.slice()}get sessionDescriptionHandlerOptions(){return this._sessionDescriptionHandlerOptions||{}}set sessionDescriptionHandlerOptions(e){this._sessionDescriptionHandlerOptions=Object.assign({},e)}get sessionDescriptionHandlerModifiersReInvite(){return this._sessionDescriptionHandlerModifiersReInvite||[]}set sessionDescriptionHandlerModifiersReInvite(e){this._sessionDescriptionHandlerModifiersReInvite=e.slice()}get sessionDescriptionHandlerOptionsReInvite(){return this._sessionDescriptionHandlerOptionsReInvite||{}}set sessionDescriptionHandlerOptionsReInvite(e){this._sessionDescriptionHandlerOptionsReInvite=Object.assign({},e)}get state(){return this._state}get stateChange(){return this._stateEventEmitter}get userAgent(){return this._userAgent}bye(e={}){let t="Session.bye() may only be called if established session.";switch(this.state){case w.Initial:typeof this.cancel=="function"?(t+=" However Inviter.invite() has not yet been called.",t+=" Perhaps you should have called Inviter.cancel()?"):typeof this.reject=="function"&&(t+=" However Invitation.accept() has not yet been called.",t+=" Perhaps you should have called Invitation.reject()?");break;case w.Establishing:typeof this.cancel=="function"?(t+=" However a dialog does not yet exist.",t+=" Perhaps you should have called Inviter.cancel()?"):typeof this.reject=="function"&&(t+=" However Invitation.accept() has not yet been called (or not yet resolved).",t+=" Perhaps you should have called Invitation.reject()?");break;case w.Established:{const i=e.requestDelegate,s=this.copyRequestOptions(e.requestOptions);return this._bye(i,s)}case w.Terminating:t+=" However this session is already terminating.",typeof this.cancel=="function"?t+=" Perhaps you have already called Inviter.cancel()?":typeof this.reject=="function"&&(t+=" Perhaps you have already called Session.bye()?");break;case w.Terminated:t+=" However this session is already terminated.";break;default:throw new Error("Unknown state")}return this.logger.error(t),Promise.reject(new Error(`Invalid session state ${this.state}`))}info(e={}){if(this.state!==w.Established)return this.logger.error("Session.info() may only be called if established session."),Promise.reject(new Error(`Invalid session state ${this.state}`));const t=e.requestDelegate,i=this.copyRequestOptions(e.requestOptions);return this._info(t,i)}invite(e={}){if(this.logger.log("Session.invite"),this.state!==w.Established)return Promise.reject(new Error(`Invalid session state ${this.state}`));if(this.pendingReinvite)return Promise.reject(new ve("Reinvite in progress. Please wait until complete, then try again."));this.pendingReinvite=!0,e.sessionDescriptionHandlerModifiers&&(this.sessionDescriptionHandlerModifiersReInvite=e.sessionDescriptionHandlerModifiers),e.sessionDescriptionHandlerOptions&&(this.sessionDescriptionHandlerOptionsReInvite=e.sessionDescriptionHandlerOptions);const t={onAccept:r=>{const n=Ee(r.message);if(!n){this.logger.error("Received 2xx response to re-INVITE without a session description"),this.ackAndBye(r,400,"Missing session description"),this.stateTransition(w.Terminated),this.pendingReinvite=!1;return}if(e.withoutSdp){const o={sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptionsReInvite,sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiersReInvite};this.setOfferAndGetAnswer(n,o).then(d=>{r.ack({body:d})}).catch(d=>{this.logger.error("Failed to handle offer in 2xx response to re-INVITE"),this.logger.error(d.message),this.state===w.Terminated?r.ack():(this.ackAndBye(r,488,"Bad Media Description"),this.stateTransition(w.Terminated))}).then(()=>{this.pendingReinvite=!1,e.requestDelegate&&e.requestDelegate.onAccept&&e.requestDelegate.onAccept(r)})}else{const o={sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptionsReInvite,sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiersReInvite};this.setAnswer(n,o).then(()=>{r.ack()}).catch(d=>{this.logger.error("Failed to handle answer in 2xx response to re-INVITE"),this.logger.error(d.message),this.state!==w.Terminated?(this.ackAndBye(r,488,"Bad Media Description"),this.stateTransition(w.Terminated)):r.ack()}).then(()=>{this.pendingReinvite=!1,e.requestDelegate&&e.requestDelegate.onAccept&&e.requestDelegate.onAccept(r)})}},onProgress:r=>{},onRedirect:r=>{},onReject:r=>{this.logger.warn("Received a non-2xx response to re-INVITE"),this.pendingReinvite=!1,e.withoutSdp?e.requestDelegate&&e.requestDelegate.onReject&&e.requestDelegate.onReject(r):this.rollbackOffer().catch(n=>{if(this.logger.error("Failed to rollback offer on non-2xx response to re-INVITE"),this.logger.error(n.message),this.state!==w.Terminated){if(!this.dialog)throw new Error("Dialog undefined.");const o=[];o.push("Reason: "+this.getReasonHeaderValue(500,"Internal Server Error")),this.dialog.bye(void 0,{extraHeaders:o}),this.stateTransition(w.Terminated)}}).then(()=>{e.requestDelegate&&e.requestDelegate.onReject&&e.requestDelegate.onReject(r)})},onTrying:r=>{}},i=e.requestOptions||{};if(i.extraHeaders=(i.extraHeaders||[]).slice(),i.extraHeaders.push("Allow: "+ae.toString()),i.extraHeaders.push("Contact: "+this._contact),e.withoutSdp){if(!this.dialog)throw this.pendingReinvite=!1,new Error("Dialog undefined.");return Promise.resolve(this.dialog.invite(t,i))}const s={sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptionsReInvite,sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiersReInvite};return this.getOffer(s).then(r=>{if(!this.dialog)throw this.pendingReinvite=!1,new Error("Dialog undefined.");return i.body=r,this.dialog.invite(t,i)}).catch(r=>{throw this.logger.error(r.message),this.logger.error("Failed to send re-INVITE"),this.pendingReinvite=!1,r})}message(e={}){if(this.state!==w.Established)return this.logger.error("Session.message() may only be called if established session."),Promise.reject(new Error(`Invalid session state ${this.state}`));const t=e.requestDelegate,i=this.copyRequestOptions(e.requestOptions);return this._message(t,i)}refer(e,t={}){if(this.state!==w.Established)return this.logger.error("Session.refer() may only be called if established session."),Promise.reject(new Error(`Invalid session state ${this.state}`));if(e instanceof we&&!e.dialog)return this.logger.error("Session.refer() may only be called with session which is established. You are perhaps attempting to attended transfer to a target for which there is not dialog yet established. Perhaps you are attempting a 'semi-attended' tansfer? Regardless, this is not supported. The recommended approached is to check to see if the target Session is in the Established state before calling refer(); if the state is not Established you may proceed by falling back using a URI as the target (blind transfer)."),Promise.reject(new Error(`Invalid session state ${this.state}`));const i=t.requestDelegate,s=this.copyRequestOptions(t.requestOptions);return s.extraHeaders=s.extraHeaders?s.extraHeaders.concat(this.referExtraHeaders(this.referToString(e))):this.referExtraHeaders(this.referToString(e)),this._refer(t.onNotify,i,s)}_bye(e,t){if(!this.dialog)return Promise.reject(new Error("Session dialog undefined."));const i=this.dialog;switch(i.sessionState){case V.Initial:throw new Error(`Invalid dialog state ${i.sessionState}`);case V.Early:throw new Error(`Invalid dialog state ${i.sessionState}`);case V.AckWait:return this.stateTransition(w.Terminating),new Promise(s=>{i.delegate={onAck:()=>{const r=i.bye(e,t);return this.stateTransition(w.Terminated),s(r),Promise.resolve()},onAckTimeout:()=>{const r=i.bye(e,t);this.stateTransition(w.Terminated),s(r)}}});case V.Confirmed:{const s=i.bye(e,t);return this.stateTransition(w.Terminated),Promise.resolve(s)}case V.Terminated:throw new Error(`Invalid dialog state ${i.sessionState}`);default:throw new Error("Unrecognized state.")}}_info(e,t){return this.dialog?Promise.resolve(this.dialog.info(e,t)):Promise.reject(new Error("Session dialog undefined."))}_message(e,t){return this.dialog?Promise.resolve(this.dialog.message(e,t)):Promise.reject(new Error("Session dialog undefined."))}_refer(e,t,i){return this.dialog?(this.onNotify=e,Promise.resolve(this.dialog.refer(t,i))):Promise.reject(new Error("Session dialog undefined."))}ackAndBye(e,t,i){e.ack();const s=[];t&&s.push("Reason: "+this.getReasonHeaderValue(t,i)),e.session.bye(void 0,{extraHeaders:s})}onAckRequest(e){if(this.logger.log("Session.onAckRequest"),this.state!==w.Established&&this.state!==w.Terminating)return this.logger.error(`ACK received while in state ${this.state}, dropping request`),Promise.resolve();const t=this.dialog;if(!t)throw new Error("Dialog undefined.");const i={sessionDescriptionHandlerOptions:this.pendingReinviteAck?this.sessionDescriptionHandlerOptionsReInvite:this.sessionDescriptionHandlerOptions,sessionDescriptionHandlerModifiers:this.pendingReinviteAck?this._sessionDescriptionHandlerModifiersReInvite:this._sessionDescriptionHandlerModifiers};if(this.delegate&&this.delegate.onAck){const s=new Ht(e);this.delegate.onAck(s)}switch(this.pendingReinviteAck=!1,t.signalingState){case y.Initial:{this.logger.error(`Invalid signaling state ${t.signalingState}.`);const s=["Reason: "+this.getReasonHeaderValue(488,"Bad Media Description")];return t.bye(void 0,{extraHeaders:s}),this.stateTransition(w.Terminated),Promise.resolve()}case y.Stable:{const s=Ee(e.message);return s?s.contentDisposition==="render"?(this._renderbody=s.content,this._rendertype=s.contentType,Promise.resolve()):s.contentDisposition!=="session"?Promise.resolve():this.setAnswer(s,i).catch(r=>{this.logger.error(r.message);const n=["Reason: "+this.getReasonHeaderValue(488,"Bad Media Description")];t.bye(void 0,{extraHeaders:n}),this.stateTransition(w.Terminated)}):Promise.resolve()}case y.HaveLocalOffer:{this.logger.error(`Invalid signaling state ${t.signalingState}.`);const s=["Reason: "+this.getReasonHeaderValue(488,"Bad Media Description")];return t.bye(void 0,{extraHeaders:s}),this.stateTransition(w.Terminated),Promise.resolve()}case y.HaveRemoteOffer:{this.logger.error(`Invalid signaling state ${t.signalingState}.`);const s=["Reason: "+this.getReasonHeaderValue(488,"Bad Media Description")];return t.bye(void 0,{extraHeaders:s}),this.stateTransition(w.Terminated),Promise.resolve()}case y.Closed:throw new Error(`Invalid signaling state ${t.signalingState}.`);default:throw new Error(`Invalid signaling state ${t.signalingState}.`)}}onByeRequest(e){if(this.logger.log("Session.onByeRequest"),this.state!==w.Established){this.logger.error(`BYE received while in state ${this.state}, dropping request`);return}if(this.delegate&&this.delegate.onBye){const t=new Mt(e);this.delegate.onBye(t)}else e.accept();this.stateTransition(w.Terminated)}onInfoRequest(e){if(this.logger.log("Session.onInfoRequest"),this.state!==w.Established){this.logger.error(`INFO received while in state ${this.state}, dropping request`);return}if(this.delegate&&this.delegate.onInfo){const t=new Ot(e);this.delegate.onInfo(t)}else e.accept()}onInviteRequest(e){if(this.logger.log("Session.onInviteRequest"),this.state!==w.Established){this.logger.error(`INVITE received while in state ${this.state}, dropping request`);return}this.pendingReinviteAck=!0;const t=["Contact: "+this._contact];if(e.message.hasHeader("P-Asserted-Identity")){const s=e.message.getHeader("P-Asserted-Identity");if(!s)throw new Error("Header undefined.");this._assertedIdentity=P.nameAddrHeaderParse(s)}const i={sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptionsReInvite,sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiersReInvite};this.generateResponseOfferAnswerInDialog(i).then(s=>{const r=e.accept({statusCode:200,extraHeaders:t,body:s});this.delegate&&this.delegate.onInvite&&this.delegate.onInvite(e.message,r.message,200)}).catch(s=>{if(this.logger.error(s.message),this.logger.error("Failed to handle to re-INVITE request"),!this.dialog)throw new Error("Dialog undefined.");if(this.logger.error(this.dialog.signalingState),this.dialog.signalingState===y.Stable){const r=e.reject({statusCode:488});this.delegate&&this.delegate.onInvite&&this.delegate.onInvite(e.message,r.message,488);return}this.rollbackOffer().then(()=>{const r=e.reject({statusCode:488});this.delegate&&this.delegate.onInvite&&this.delegate.onInvite(e.message,r.message,488)}).catch(r=>{this.logger.error(r.message),this.logger.error("Failed to rollback offer on re-INVITE request");const n=e.reject({statusCode:488});if(this.state!==w.Terminated){if(!this.dialog)throw new Error("Dialog undefined.");const o=[];o.push("Reason: "+this.getReasonHeaderValue(500,"Internal Server Error")),this.dialog.bye(void 0,{extraHeaders:o}),this.stateTransition(w.Terminated)}this.delegate&&this.delegate.onInvite&&this.delegate.onInvite(e.message,n.message,488)})})}onMessageRequest(e){if(this.logger.log("Session.onMessageRequest"),this.state!==w.Established){this.logger.error(`MESSAGE received while in state ${this.state}, dropping request`);return}if(this.delegate&&this.delegate.onMessage){const t=new ct(e);this.delegate.onMessage(t)}else e.accept()}onNotifyRequest(e){if(this.logger.log("Session.onNotifyRequest"),this.state!==w.Established){this.logger.error(`NOTIFY received while in state ${this.state}, dropping request`);return}if(this.onNotify){const t=new Be(e);this.onNotify(t);return}if(this.delegate&&this.delegate.onNotify){const t=new Be(e);this.delegate.onNotify(t)}else e.accept()}onPrackRequest(e){if(this.logger.log("Session.onPrackRequest"),this.state!==w.Established){this.logger.error(`PRACK received while in state ${this.state}, dropping request`);return}throw new Error("Unimplemented.")}onReferRequest(e){if(this.logger.log("Session.onReferRequest"),this.state!==w.Established){this.logger.error(`REFER received while in state ${this.state}, dropping request`);return}if(!e.message.hasHeader("refer-to")){this.logger.warn("Invalid REFER packet. A refer-to header is required. Rejecting."),e.reject();return}const t=new Bt(e,this);this.delegate&&this.delegate.onRefer?this.delegate.onRefer(t):(this.logger.log("No delegate available to handle REFER, automatically accepting and following."),t.accept().then(()=>t.makeInviter(this._referralInviterOptions).invite()).catch(i=>{this.logger.error(i.message)}))}generateResponseOfferAnswer(e,t){if(this.dialog)return this.generateResponseOfferAnswerInDialog(t);const i=Ee(e.message);return!i||i.contentDisposition!=="session"?this.getOffer(t):this.setOfferAndGetAnswer(i,t)}generateResponseOfferAnswerInDialog(e){if(!this.dialog)throw new Error("Dialog undefined.");switch(this.dialog.signalingState){case y.Initial:return this.getOffer(e);case y.HaveLocalOffer:return Promise.resolve(void 0);case y.HaveRemoteOffer:if(!this.dialog.offer)throw new Error(`Session offer undefined in signaling state ${this.dialog.signalingState}.`);return this.setOfferAndGetAnswer(this.dialog.offer,e);case y.Stable:return this.state!==w.Established?Promise.resolve(void 0):this.getOffer(e);case y.Closed:throw new Error(`Invalid signaling state ${this.dialog.signalingState}.`);default:throw new Error(`Invalid signaling state ${this.dialog.signalingState}.`)}}getOffer(e){const t=this.setupSessionDescriptionHandler(),i=e.sessionDescriptionHandlerOptions,s=e.sessionDescriptionHandlerModifiers;try{return t.getDescription(i,s).then(r=>De(r)).catch(r=>{this.logger.error("Session.getOffer: SDH getDescription rejected...");const n=r instanceof Error?r:new Error("Session.getOffer unknown error.");throw this.logger.error(n.message),n})}catch(r){this.logger.error("Session.getOffer: SDH getDescription threw...");const n=r instanceof Error?r:new Error(r);return this.logger.error(n.message),Promise.reject(n)}}rollbackOffer(){const e=this.setupSessionDescriptionHandler();if(e.rollbackDescription===void 0)return Promise.resolve();try{return e.rollbackDescription().catch(t=>{this.logger.error("Session.rollbackOffer: SDH rollbackDescription rejected...");const i=t instanceof Error?t:new Error("Session.rollbackOffer unknown error.");throw this.logger.error(i.message),i})}catch(t){this.logger.error("Session.rollbackOffer: SDH rollbackDescription threw...");const i=t instanceof Error?t:new Error(t);return this.logger.error(i.message),Promise.reject(i)}}setAnswer(e,t){const i=this.setupSessionDescriptionHandler(),s=t.sessionDescriptionHandlerOptions,r=t.sessionDescriptionHandlerModifiers;try{if(!i.hasDescription(e.contentType))return Promise.reject(new Ne)}catch(n){this.logger.error("Session.setAnswer: SDH hasDescription threw...");const o=n instanceof Error?n:new Error(n);return this.logger.error(o.message),Promise.reject(o)}try{return i.setDescription(e.content,s,r).catch(n=>{this.logger.error("Session.setAnswer: SDH setDescription rejected...");const o=n instanceof Error?n:new Error("Session.setAnswer unknown error.");throw this.logger.error(o.message),o})}catch(n){this.logger.error("Session.setAnswer: SDH setDescription threw...");const o=n instanceof Error?n:new Error(n);return this.logger.error(o.message),Promise.reject(o)}}setOfferAndGetAnswer(e,t){const i=this.setupSessionDescriptionHandler(),s=t.sessionDescriptionHandlerOptions,r=t.sessionDescriptionHandlerModifiers;try{if(!i.hasDescription(e.contentType))return Promise.reject(new Ne)}catch(n){this.logger.error("Session.setOfferAndGetAnswer: SDH hasDescription threw...");const o=n instanceof Error?n:new Error(n);return this.logger.error(o.message),Promise.reject(o)}try{return i.setDescription(e.content,s,r).then(()=>i.getDescription(s,r)).then(n=>De(n)).catch(n=>{this.logger.error("Session.setOfferAndGetAnswer: SDH setDescription or getDescription rejected...");const o=n instanceof Error?n:new Error("Session.setOfferAndGetAnswer unknown error.");throw this.logger.error(o.message),o})}catch(n){this.logger.error("Session.setOfferAndGetAnswer: SDH setDescription or getDescription threw...");const o=n instanceof Error?n:new Error(n);return this.logger.error(o.message),Promise.reject(o)}}setSessionDescriptionHandler(e){if(this._sessionDescriptionHandler)throw new Error("Session description handler defined.");this._sessionDescriptionHandler=e}setupSessionDescriptionHandler(){var e;return this._sessionDescriptionHandler?this._sessionDescriptionHandler:(this._sessionDescriptionHandler=this.sessionDescriptionHandlerFactory(this,this.userAgent.configuration.sessionDescriptionHandlerFactoryOptions),!((e=this.delegate)===null||e===void 0)&&e.onSessionDescriptionHandler&&this.delegate.onSessionDescriptionHandler(this._sessionDescriptionHandler,!1),this._sessionDescriptionHandler)}stateTransition(e){const t=()=>{throw new Error(`Invalid state transition from ${this._state} to ${e}`)};switch(this._state){case w.Initial:e!==w.Establishing&&e!==w.Established&&e!==w.Terminating&&e!==w.Terminated&&t();break;case w.Establishing:e!==w.Established&&e!==w.Terminating&&e!==w.Terminated&&t();break;case w.Established:e!==w.Terminating&&e!==w.Terminated&&t();break;case w.Terminating:e!==w.Terminated&&t();break;case w.Terminated:t();break;default:throw new Error("Unrecognized state.")}this._state=e,this.logger.log(`Session ${this.id} transitioned to state ${this._state}`),this._stateEventEmitter.emit(this._state),e===w.Terminated&&this.dispose()}copyRequestOptions(e={}){const t=e.extraHeaders?e.extraHeaders.slice():void 0,i=e.body?{contentDisposition:e.body.contentDisposition||"render",contentType:e.body.contentType||"text/plain",content:e.body.content||""}:void 0;return{extraHeaders:t,body:i}}getReasonHeaderValue(e,t){const i=e;let s=Ae(e);return!s&&t&&(s=t),"SIP;cause="+i+';text="'+s+'"'}referExtraHeaders(e){const t=[];return t.push("Referred-By: <"+this.userAgent.configuration.uri+">"),t.push("Contact: "+this._contact),t.push("Allow: "+["ACK","CANCEL","INVITE","MESSAGE","BYE","OPTIONS","INFO","NOTIFY","REFER"].toString()),t.push("Refer-To: "+e),t}referToString(e){let t;if(e instanceof z)t=e.toString();else{if(!e.dialog)throw new Error("Dialog undefined.");const i=e.remoteIdentity.friendlyName,s=e.dialog.remoteTarget.toString(),r=e.dialog.callId,n=e.dialog.remoteTag,o=e.dialog.localTag,d=encodeURIComponent(`${r};to-tag=${n};from-tag=${o}`);t=`"${i}" <${s}?Replaces=${d}>`}return t}}var W;(function(a){a.Required="Required",a.Supported="Supported",a.Unsupported="Unsupported"})(W=W||(W={}));const jt={"100rel":!0,199:!0,answermode:!0,"early-session":!0,eventlist:!0,explicitsub:!0,"from-change":!0,"geolocation-http":!0,"geolocation-sip":!0,gin:!0,gruu:!0,histinfo:!0,ice:!0,join:!0,"multiple-refer":!0,norefersub:!0,nosub:!0,outbound:!0,path:!0,policy:!0,precondition:!0,pref:!0,privacy:!0,"recipient-list-invite":!0,"recipient-list-message":!0,"recipient-list-subscribe":!0,replaces:!0,"resource-priority":!0,"sdp-anat":!0,"sec-agree":!0,tdialog:!0,timer:!0,uui:!0};class fe extends we{constructor(e,t){super(e),this.incomingInviteRequest=t,this.disposed=!1,this.expiresTimer=void 0,this.isCanceled=!1,this.rel100="none",this.rseq=Math.floor(Math.random()*1e4),this.userNoAnswerTimer=void 0,this.waitingForPrack=!1,this.logger=e.getLogger("sip.Invitation");const i=this.incomingInviteRequest.message,s=i.getHeader("require");s&&s.toLowerCase().includes("100rel")&&(this.rel100="required");const r=i.getHeader("supported");if(r&&r.toLowerCase().includes("100rel")&&(this.rel100="supported"),i.toTag=t.toTag,typeof i.toTag!="string")throw new TypeError("toTag should have been a string.");if(this.userNoAnswerTimer=setTimeout(()=>{t.reject({statusCode:480}),this.stateTransition(w.Terminated)},this.userAgent.configuration.noAnswerTimeout?this.userAgent.configuration.noAnswerTimeout*1e3:6e4),i.hasHeader("expires")){const d=Number(i.getHeader("expires")||0)*1e3;this.expiresTimer=setTimeout(()=>{this.state===w.Initial&&(t.reject({statusCode:487}),this.stateTransition(w.Terminated))},d)}const n=this.request.getHeader("P-Asserted-Identity");n&&(this._assertedIdentity=P.nameAddrHeaderParse(n)),this._contact=this.userAgent.contact.toString();const o=i.parseHeader("Content-Disposition");o&&o.type==="render"&&(this._renderbody=i.body,this._rendertype=i.getHeader("Content-Type")),this._id=i.callId+i.fromTag,this.userAgent._sessions[this._id]=this}dispose(){if(this.disposed)return Promise.resolve();switch(this.disposed=!0,this.expiresTimer&&(clearTimeout(this.expiresTimer),this.expiresTimer=void 0),this.userNoAnswerTimer&&(clearTimeout(this.userNoAnswerTimer),this.userNoAnswerTimer=void 0),this.prackNeverArrived(),this.state){case w.Initial:return this.reject().then(()=>super.dispose());case w.Establishing:return this.reject().then(()=>super.dispose());case w.Established:return super.dispose();case w.Terminating:return super.dispose();case w.Terminated:return super.dispose();default:throw new Error("Unknown state.")}}get autoSendAnInitialProvisionalResponse(){return this.rel100!=="required"&&this.userAgent.configuration.sendInitialProvisionalResponse}get body(){return this.incomingInviteRequest.message.body}get localIdentity(){return this.request.to}get remoteIdentity(){return this.request.from}get request(){return this.incomingInviteRequest.message}accept(e={}){if(this.logger.log("Invitation.accept"),this.state!==w.Initial){const t=new Error(`Invalid session state ${this.state}`);return this.logger.error(t.message),Promise.reject(t)}return e.sessionDescriptionHandlerModifiers&&(this.sessionDescriptionHandlerModifiers=e.sessionDescriptionHandlerModifiers),e.sessionDescriptionHandlerOptions&&(this.sessionDescriptionHandlerOptions=e.sessionDescriptionHandlerOptions),this.stateTransition(w.Establishing),this.sendAccept(e).then(({message:t,session:i})=>{i.delegate={onAck:s=>this.onAckRequest(s),onAckTimeout:()=>this.onAckTimeout(),onBye:s=>this.onByeRequest(s),onInfo:s=>this.onInfoRequest(s),onInvite:s=>this.onInviteRequest(s),onMessage:s=>this.onMessageRequest(s),onNotify:s=>this.onNotifyRequest(s),onPrack:s=>this.onPrackRequest(s),onRefer:s=>this.onReferRequest(s)},this._dialog=i,this.stateTransition(w.Established),this._replacee&&this._replacee._bye()}).catch(t=>this.handleResponseError(t))}progress(e={}){if(this.logger.log("Invitation.progress"),this.state!==w.Initial){const i=new Error(`Invalid session state ${this.state}`);return this.logger.error(i.message),Promise.reject(i)}const t=e.statusCode||180;if(t<100||t>199)throw new TypeError("Invalid statusCode: "+t);return e.sessionDescriptionHandlerModifiers&&(this.sessionDescriptionHandlerModifiers=e.sessionDescriptionHandlerModifiers),e.sessionDescriptionHandlerOptions&&(this.sessionDescriptionHandlerOptions=e.sessionDescriptionHandlerOptions),this.waitingForPrack?(this.logger.warn("Unexpected call for progress while waiting for prack, ignoring"),Promise.resolve()):e.statusCode===100?this.sendProgressTrying().then(()=>{}).catch(i=>this.handleResponseError(i)):this.rel100!=="required"&&!(this.rel100==="supported"&&e.rel100)&&!(this.rel100==="supported"&&this.userAgent.configuration.sipExtension100rel===W.Required)?this.sendProgress(e).then(()=>{}).catch(i=>this.handleResponseError(i)):this.sendProgressReliableWaitForPrack(e).then(()=>{}).catch(i=>this.handleResponseError(i))}reject(e={}){if(this.logger.log("Invitation.reject"),this.state!==w.Initial&&this.state!==w.Establishing){const n=new Error(`Invalid session state ${this.state}`);return this.logger.error(n.message),Promise.reject(n)}const t=e.statusCode||480,i=e.reasonPhrase?e.reasonPhrase:Ae(t),s=e.extraHeaders||[];if(t<300||t>699)throw new TypeError("Invalid statusCode: "+t);const r=e.body?De(e.body):void 0;return t<400?this.incomingInviteRequest.redirect([],{statusCode:t,reasonPhrase:i,extraHeaders:s,body:r}):this.incomingInviteRequest.reject({statusCode:t,reasonPhrase:i,extraHeaders:s,body:r}),this.stateTransition(w.Terminated),Promise.resolve()}_onCancel(e){if(this.logger.log("Invitation._onCancel"),this.state!==w.Initial&&this.state!==w.Establishing){this.logger.error(`CANCEL received while in state ${this.state}, dropping request`);return}if(this.delegate&&this.delegate.onCancel){const t=new qt(e);this.delegate.onCancel(t)}this.isCanceled=!0,this.incomingInviteRequest.reject({statusCode:487}),this.stateTransition(w.Terminated)}handlePrackOfferAnswer(e){if(!this.dialog)throw new Error("Dialog undefined.");const t=Ee(e.message);if(!t||t.contentDisposition!=="session")return Promise.resolve(void 0);const i={sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptions,sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiers};switch(this.dialog.signalingState){case y.Initial:throw new Error(`Invalid signaling state ${this.dialog.signalingState}.`);case y.Stable:return this.setAnswer(t,i).then(()=>{});case y.HaveLocalOffer:throw new Error(`Invalid signaling state ${this.dialog.signalingState}.`);case y.HaveRemoteOffer:return this.setOfferAndGetAnswer(t,i);case y.Closed:throw new Error(`Invalid signaling state ${this.dialog.signalingState}.`);default:throw new Error(`Invalid signaling state ${this.dialog.signalingState}.`)}}handleResponseError(e){let t=480;if(e instanceof Error?this.logger.error(e.message):this.logger.error(e),e instanceof Ne?(this.logger.error("A session description handler occurred while sending response (content type unsupported"),t=415):e instanceof kt?this.logger.error("A session description handler occurred while sending response"):e instanceof Ue?this.logger.error("Session ended before response could be formulated and sent (while waiting for PRACK)"):e instanceof ne&&this.logger.error("Session changed state before response could be formulated and sent"),this.state===w.Initial||this.state===w.Establishing)try{this.incomingInviteRequest.reject({statusCode:t}),this.stateTransition(w.Terminated)}catch(i){throw this.logger.error("An error occurred attempting to reject the request while handling another error"),i}if(this.isCanceled){this.logger.warn("An error occurred while attempting to formulate and send a response to an incoming INVITE. However a CANCEL was received and processed while doing so which can (and often does) result in errors occurring as the session terminates in the meantime. Said error is being ignored.");return}throw e}onAckTimeout(){if(this.logger.log("Invitation.onAckTimeout"),!this.dialog)throw new Error("Dialog undefined.");this.logger.log("No ACK received for an extended period of time, terminating session"),this.dialog.bye(),this.stateTransition(w.Terminated)}sendAccept(e={}){const t={sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptions,sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiers},i=e.extraHeaders||[];return this.waitingForPrack?this.waitForArrivalOfPrack().then(()=>clearTimeout(this.userNoAnswerTimer)).then(()=>this.generateResponseOfferAnswer(this.incomingInviteRequest,t)).then(s=>this.incomingInviteRequest.accept({statusCode:200,body:s,extraHeaders:i})):(clearTimeout(this.userNoAnswerTimer),this.generateResponseOfferAnswer(this.incomingInviteRequest,t).then(s=>this.incomingInviteRequest.accept({statusCode:200,body:s,extraHeaders:i})))}sendProgress(e={}){const t=e.statusCode||180,i=e.reasonPhrase,s=(e.extraHeaders||[]).slice(),r=e.body?De(e.body):void 0;if(t===183&&!r)return this.sendProgressWithSDP(e);try{const n=this.incomingInviteRequest.progress({statusCode:t,reasonPhrase:i,extraHeaders:s,body:r});return this._dialog=n.session,Promise.resolve(n)}catch(n){return Promise.reject(n)}}sendProgressWithSDP(e={}){const t={sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptions,sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiers},i=e.statusCode||183,s=e.reasonPhrase,r=(e.extraHeaders||[]).slice();return this.generateResponseOfferAnswer(this.incomingInviteRequest,t).then(n=>this.incomingInviteRequest.progress({statusCode:i,reasonPhrase:s,extraHeaders:r,body:n})).then(n=>(this._dialog=n.session,n))}sendProgressReliable(e={}){return e.extraHeaders=(e.extraHeaders||[]).slice(),e.extraHeaders.push("Require: 100rel"),e.extraHeaders.push("RSeq: "+Math.floor(Math.random()*1e4)),this.sendProgressWithSDP(e)}sendProgressReliableWaitForPrack(e={}){const t={sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptions,sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiers},i=e.statusCode||183,s=e.reasonPhrase,r=(e.extraHeaders||[]).slice();r.push("Require: 100rel"),r.push("RSeq: "+this.rseq++);let n;return new Promise((o,d)=>{this.waitingForPrack=!0,this.generateResponseOfferAnswer(this.incomingInviteRequest,t).then(u=>(n=u,this.incomingInviteRequest.progress({statusCode:i,reasonPhrase:s,extraHeaders:r,body:n}))).then(u=>{this._dialog=u.session;let h,m;u.session.delegate={onPrack:p=>{h=p,clearTimeout(x),clearTimeout(Q),this.waitingForPrack&&(this.waitingForPrack=!1,this.handlePrackOfferAnswer(h).then($=>{try{m=h.accept({statusCode:200,body:$}),this.prackArrived(),o({prackRequest:h,prackResponse:m,progressResponse:u})}catch(et){d(et)}}).catch($=>d($)))}};const x=setTimeout(()=>{this.waitingForPrack&&(this.waitingForPrack=!1,this.logger.warn("No PRACK received, rejecting INVITE."),clearTimeout(Q),this.reject({statusCode:504}).then(()=>d(new Ue)).catch(p=>d(p)))},M.T1*64),_=()=>{try{this.incomingInviteRequest.progress({statusCode:i,reasonPhrase:s,extraHeaders:r,body:n})}catch(p){this.waitingForPrack=!1,d(p);return}Q=setTimeout(_,C*=2)};let C=M.T1,Q=setTimeout(_,C)}).catch(u=>{this.waitingForPrack=!1,d(u)})})}sendProgressTrying(){try{const e=this.incomingInviteRequest.trying();return Promise.resolve(e)}catch(e){return Promise.reject(e)}}waitForArrivalOfPrack(){if(this.waitingForPrackPromise)throw new Error("Already waiting for PRACK");return this.waitingForPrackPromise=new Promise((e,t)=>{this.waitingForPrackResolve=e,this.waitingForPrackReject=t}),this.waitingForPrackPromise}prackArrived(){this.waitingForPrackResolve&&this.waitingForPrackResolve(),this.waitingForPrackPromise=void 0,this.waitingForPrackResolve=void 0,this.waitingForPrackReject=void 0}prackNeverArrived(){this.waitingForPrackReject&&this.waitingForPrackReject(new Ue),this.waitingForPrackPromise=void 0,this.waitingForPrackResolve=void 0,this.waitingForPrackReject=void 0}}class Pe extends we{constructor(e,t,i={}){super(e,i),this.disposed=!1,this.earlyMedia=!1,this.earlyMediaSessionDescriptionHandlers=new Map,this.isCanceled=!1,this.inviteWithoutSdp=!1,this.logger=e.getLogger("sip.Inviter"),this.earlyMedia=i.earlyMedia!==void 0?i.earlyMedia:this.earlyMedia,this.fromTag=$e(),this.inviteWithoutSdp=i.inviteWithoutSdp!==void 0?i.inviteWithoutSdp:this.inviteWithoutSdp;const s=Object.assign({},i);s.params=Object.assign({},i.params);const r=i.anonymous||!1,n=e.contact.toString({anonymous:r,outbound:r?!e.contact.tempGruu:!e.contact.pubGruu});r&&e.configuration.uri&&(s.params.fromDisplayName="Anonymous",s.params.fromUri="sip:anonymous@anonymous.invalid");let o=e.userAgentCore.configuration.aor;if(s.params.fromUri&&(o=typeof s.params.fromUri=="string"?P.URIParse(s.params.fromUri):s.params.fromUri),!o)throw new TypeError("Invalid from URI: "+s.params.fromUri);let d=t;if(s.params.toUri&&(d=typeof s.params.toUri=="string"?P.URIParse(s.params.toUri):s.params.toUri),!d)throw new TypeError("Invalid to URI: "+s.params.toUri);const u=Object.assign({},s.params);u.fromTag=this.fromTag;const h=(s.extraHeaders||[]).slice();r&&e.configuration.uri&&(h.push("P-Preferred-Identity: "+e.configuration.uri.toString()),h.push("Privacy: id")),h.push("Contact: "+n),h.push("Allow: "+["ACK","CANCEL","INVITE","MESSAGE","BYE","OPTIONS","INFO","NOTIFY","REFER"].toString()),e.configuration.sipExtension100rel===W.Required&&h.push("Require: 100rel"),e.configuration.sipExtensionReplaces===W.Required&&h.push("Require: replaces"),s.extraHeaders=h;const m=void 0;this.outgoingRequestMessage=e.userAgentCore.makeOutgoingRequestMessage(v.INVITE,t,o,d,u,h,m),this._contact=n,this._referralInviterOptions=s,this._renderbody=i.renderbody,this._rendertype=i.rendertype,i.sessionDescriptionHandlerModifiers&&(this.sessionDescriptionHandlerModifiers=i.sessionDescriptionHandlerModifiers),i.sessionDescriptionHandlerOptions&&(this.sessionDescriptionHandlerOptions=i.sessionDescriptionHandlerOptions),i.sessionDescriptionHandlerModifiersReInvite&&(this.sessionDescriptionHandlerModifiersReInvite=i.sessionDescriptionHandlerModifiersReInvite),i.sessionDescriptionHandlerOptionsReInvite&&(this.sessionDescriptionHandlerOptionsReInvite=i.sessionDescriptionHandlerOptionsReInvite),this._id=this.outgoingRequestMessage.callId+this.fromTag,this.userAgent._sessions[this._id]=this}dispose(){if(this.disposed)return Promise.resolve();switch(this.disposed=!0,this.disposeEarlyMedia(),this.state){case w.Initial:return this.cancel().then(()=>super.dispose());case w.Establishing:return this.cancel().then(()=>super.dispose());case w.Established:return super.dispose();case w.Terminating:return super.dispose();case w.Terminated:return super.dispose();default:throw new Error("Unknown state.")}}get body(){return this.outgoingRequestMessage.body}get localIdentity(){return this.outgoingRequestMessage.from}get remoteIdentity(){return this.outgoingRequestMessage.to}get request(){return this.outgoingRequestMessage}cancel(e={}){if(this.logger.log("Inviter.cancel"),this.state!==w.Initial&&this.state!==w.Establishing){const i=new Error(`Invalid session state ${this.state}`);return this.logger.error(i.message),Promise.reject(i)}this.isCanceled=!0,this.stateTransition(w.Terminating);function t(i,s){if(i&&i<200||i>699)throw new TypeError("Invalid statusCode: "+i);if(i){const r=i,n=Ae(i)||s;return"SIP;cause="+r+';text="'+n+'"'}}if(this.outgoingInviteRequest){let i;e.statusCode&&e.reasonPhrase&&(i=t(e.statusCode,e.reasonPhrase)),this.outgoingInviteRequest.cancel(i,e)}else this.logger.warn("Canceled session before INVITE was sent"),this.stateTransition(w.Terminated);return Promise.resolve()}invite(e={}){if(this.logger.log("Inviter.invite"),this.state!==w.Initial)return super.invite(e);if(e.sessionDescriptionHandlerModifiers&&(this.sessionDescriptionHandlerModifiers=e.sessionDescriptionHandlerModifiers),e.sessionDescriptionHandlerOptions&&(this.sessionDescriptionHandlerOptions=e.sessionDescriptionHandlerOptions),e.withoutSdp||this.inviteWithoutSdp)return this._renderbody&&this._rendertype&&(this.outgoingRequestMessage.body={contentType:this._rendertype,body:this._renderbody}),this.stateTransition(w.Establishing),Promise.resolve(this.sendInvite(e));const t={sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiers,sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptions};return this.getOffer(t).then(i=>(this.outgoingRequestMessage.body={body:i.content,contentType:i.contentType},this.stateTransition(w.Establishing),this.sendInvite(e))).catch(i=>{throw this.logger.log(i.message),this.state!==w.Terminated&&this.stateTransition(w.Terminated),i})}sendInvite(e={}){return this.outgoingInviteRequest=this.userAgent.userAgentCore.invite(this.outgoingRequestMessage,{onAccept:t=>{if(this.dialog){this.logger.log("Additional confirmed dialog, sending ACK and BYE"),this.ackAndBye(t);return}if(this.isCanceled){this.logger.log("Canceled session accepted, sending ACK and BYE"),this.ackAndBye(t),this.stateTransition(w.Terminated);return}this.notifyReferer(t),this.onAccept(t).then(()=>{this.disposeEarlyMedia()}).catch(()=>{this.disposeEarlyMedia()}).then(()=>{e.requestDelegate&&e.requestDelegate.onAccept&&e.requestDelegate.onAccept(t)})},onProgress:t=>{this.isCanceled||(this.notifyReferer(t),this.onProgress(t).catch(()=>{this.disposeEarlyMedia()}).then(()=>{e.requestDelegate&&e.requestDelegate.onProgress&&e.requestDelegate.onProgress(t)}))},onRedirect:t=>{this.notifyReferer(t),this.onRedirect(t),e.requestDelegate&&e.requestDelegate.onRedirect&&e.requestDelegate.onRedirect(t)},onReject:t=>{this.notifyReferer(t),this.onReject(t),e.requestDelegate&&e.requestDelegate.onReject&&e.requestDelegate.onReject(t)},onTrying:t=>{this.notifyReferer(t),this.onTrying(t),e.requestDelegate&&e.requestDelegate.onTrying&&e.requestDelegate.onTrying(t)}}),this.outgoingInviteRequest}disposeEarlyMedia(){this.earlyMediaSessionDescriptionHandlers.forEach(e=>{e.close()}),this.earlyMediaSessionDescriptionHandlers.clear()}notifyReferer(e){if(!this._referred)return;if(!(this._referred instanceof we))throw new Error("Referred session not instance of session");if(!this._referred.dialog)return;if(!e.message.statusCode)throw new Error("Status code undefined.");if(!e.message.reasonPhrase)throw new Error("Reason phrase undefined.");const t=e.message.statusCode,i=e.message.reasonPhrase,s=`SIP/2.0 ${t} ${i}`.trim(),r=this._referred.dialog.notify(void 0,{extraHeaders:["Event: refer","Subscription-State: terminated"],body:{contentDisposition:"render",contentType:"message/sipfrag",content:s}});r.delegate={onReject:()=>{this._referred=void 0}}}onAccept(e){if(this.logger.log("Inviter.onAccept"),this.state!==w.Establishing)return this.logger.error(`Accept received while in state ${this.state}, dropping response`),Promise.reject(new Error(`Invalid session state ${this.state}`));const t=e.message,i=e.session;switch(t.hasHeader("P-Asserted-Identity")&&(this._assertedIdentity=P.nameAddrHeaderParse(t.getHeader("P-Asserted-Identity"))),i.delegate={onAck:s=>this.onAckRequest(s),onBye:s=>this.onByeRequest(s),onInfo:s=>this.onInfoRequest(s),onInvite:s=>this.onInviteRequest(s),onMessage:s=>this.onMessageRequest(s),onNotify:s=>this.onNotifyRequest(s),onPrack:s=>this.onPrackRequest(s),onRefer:s=>this.onReferRequest(s)},this._dialog=i,i.signalingState){case y.Initial:return this.logger.error("Received 2xx response to INVITE without a session description"),this.ackAndBye(e,400,"Missing session description"),this.stateTransition(w.Terminated),Promise.reject(new Error("Bad Media Description"));case y.HaveLocalOffer:return this.logger.error("Received 2xx response to INVITE without a session description"),this.ackAndBye(e,400,"Missing session description"),this.stateTransition(w.Terminated),Promise.reject(new Error("Bad Media Description"));case y.HaveRemoteOffer:{if(!this._dialog.offer)throw new Error(`Session offer undefined in signaling state ${this._dialog.signalingState}.`);const s={sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiers,sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptions};return this.setOfferAndGetAnswer(this._dialog.offer,s).then(r=>{e.ack({body:r}),this.stateTransition(w.Established)}).catch(r=>{throw this.ackAndBye(e,488,"Invalid session description"),this.stateTransition(w.Terminated),r})}case y.Stable:{if(this.earlyMediaSessionDescriptionHandlers.size>0){const n=this.earlyMediaSessionDescriptionHandlers.get(i.id);if(!n)throw new Error("Session description handler undefined.");return this.setSessionDescriptionHandler(n),this.earlyMediaSessionDescriptionHandlers.delete(i.id),e.ack(),this.stateTransition(w.Established),Promise.resolve()}if(this.earlyMediaDialog){if(this.earlyMediaDialog!==i){this.earlyMedia&&this.logger.error("You have set the 'earlyMedia' option to 'true' which requires that your INVITE requests do not fork and yet this INVITE request did in fact fork. Consequentially and not surprisingly the end point which accepted the INVITE (confirmed dialog) does not match the end point with which early media has been setup (early dialog) and thus this session is unable to proceed. In accordance with the SIP specifications, the SIP servers your end point is connected to determine if an INVITE forks and the forking behavior of those servers cannot be controlled by this library. If you wish to use early media with this library you must configure those servers accordingly. Alternatively you may set the 'earlyMedia' to 'false' which will allow this library to function with any INVITE requests which do fork.");const n=new Error("Early media dialog does not equal confirmed dialog, terminating session");return this.logger.error(n.message),this.ackAndBye(e,488,"Not Acceptable Here"),this.stateTransition(w.Terminated),Promise.reject(n)}return e.ack(),this.stateTransition(w.Established),Promise.resolve()}const s=i.answer;if(!s)throw new Error("Answer is undefined.");const r={sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiers,sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptions};return this.setAnswer(s,r).then(()=>{let n;this._renderbody&&this._rendertype&&(n={body:{contentDisposition:"render",contentType:this._rendertype,content:this._renderbody}}),e.ack(n),this.stateTransition(w.Established)}).catch(n=>{throw this.logger.error(n.message),this.ackAndBye(e,488,"Not Acceptable Here"),this.stateTransition(w.Terminated),n})}case y.Closed:return Promise.reject(new Error("Terminated."));default:throw new Error("Unknown session signaling state.")}}onProgress(e){var t;if(this.logger.log("Inviter.onProgress"),this.state!==w.Establishing)return this.logger.error(`Progress received while in state ${this.state}, dropping response`),Promise.reject(new Error(`Invalid session state ${this.state}`));if(!this.outgoingInviteRequest)throw new Error("Outgoing INVITE request undefined.");const i=e.message,s=e.session;i.hasHeader("P-Asserted-Identity")&&(this._assertedIdentity=P.nameAddrHeaderParse(i.getHeader("P-Asserted-Identity")));const r=i.getHeader("require"),n=i.getHeader("rseq"),d=!!(r&&r.includes("100rel")&&n?Number(n):void 0),u=[];switch(d&&u.push("RAck: "+i.getHeader("rseq")+" "+i.getHeader("cseq")),s.signalingState){case y.Initial:return d&&(this.logger.warn("First reliable provisional response received MUST contain an offer when INVITE does not contain an offer."),e.prack({extraHeaders:u})),Promise.resolve();case y.HaveLocalOffer:return d&&e.prack({extraHeaders:u}),Promise.resolve();case y.HaveRemoteOffer:if(!d)return this.logger.warn("Non-reliable provisional response MUST NOT contain an initial offer, discarding response."),Promise.resolve();{const h=this.sessionDescriptionHandlerFactory(this,this.userAgent.configuration.sessionDescriptionHandlerFactoryOptions||{});return!((t=this.delegate)===null||t===void 0)&&t.onSessionDescriptionHandler&&this.delegate.onSessionDescriptionHandler(h,!0),this.earlyMediaSessionDescriptionHandlers.set(s.id,h),h.setDescription(i.body,this.sessionDescriptionHandlerOptions,this.sessionDescriptionHandlerModifiers).then(()=>h.getDescription(this.sessionDescriptionHandlerOptions,this.sessionDescriptionHandlerModifiers)).then(m=>{const S={contentDisposition:"session",contentType:m.contentType,content:m.body};e.prack({extraHeaders:u,body:S})}).catch(m=>{throw this.stateTransition(w.Terminated),m})}case y.Stable:if(d&&e.prack({extraHeaders:u}),this.earlyMedia&&!this.earlyMediaDialog){this.earlyMediaDialog=s;const h=s.answer;if(!h)throw new Error("Answer is undefined.");const m={sessionDescriptionHandlerModifiers:this.sessionDescriptionHandlerModifiers,sessionDescriptionHandlerOptions:this.sessionDescriptionHandlerOptions};return this.setAnswer(h,m).catch(S=>{throw this.stateTransition(w.Terminated),S})}return Promise.resolve();case y.Closed:return Promise.reject(new Error("Terminated."));default:throw new Error("Unknown session signaling state.")}}onRedirect(e){if(this.logger.log("Inviter.onRedirect"),this.state!==w.Establishing&&this.state!==w.Terminating){this.logger.error(`Redirect received while in state ${this.state}, dropping response`);return}this.stateTransition(w.Terminated)}onReject(e){if(this.logger.log("Inviter.onReject"),this.state!==w.Establishing&&this.state!==w.Terminating){this.logger.error(`Reject received while in state ${this.state}, dropping response`);return}this.stateTransition(w.Terminated)}onTrying(e){if(this.logger.log("Inviter.onTrying"),this.state!==w.Establishing){this.logger.error(`Trying received while in state ${this.state}, dropping response`);return}}}class Vt{constructor(e,t,i,s="text/plain",r={}){this.logger=e.getLogger("sip.Messager"),r.params=r.params||{};let n=e.userAgentCore.configuration.aor;if(r.params.fromUri&&(n=typeof r.params.fromUri=="string"?P.URIParse(r.params.fromUri):r.params.fromUri),!n)throw new TypeError("Invalid from URI: "+r.params.fromUri);let o=t;if(r.params.toUri&&(o=typeof r.params.toUri=="string"?P.URIParse(r.params.toUri):r.params.toUri),!o)throw new TypeError("Invalid to URI: "+r.params.toUri);const d=r.params?Object.assign({},r.params):{},u=(r.extraHeaders||[]).slice(),m={contentDisposition:"render",contentType:s,content:i};this.request=e.userAgentCore.makeOutgoingRequestMessage(v.MESSAGE,t,n,o,d,u,m),this.userAgent=e}message(e={}){return this.userAgent.userAgentCore.request(this.request,e.requestDelegate),Promise.resolve()}}var R;(function(a){a.Initial="Initial",a.Registered="Registered",a.Unregistered="Unregistered",a.Terminated="Terminated"})(R=R||(R={}));class J{constructor(e,t={}){this.disposed=!1,this._contacts=[],this._retryAfter=void 0,this._state=R.Initial,this._waiting=!1,this._stateEventEmitter=new Te,this._waitingEventEmitter=new Te,this.userAgent=e;const i=e.configuration.uri.clone();if(i.user=void 0,this.options=Object.assign(Object.assign(Object.assign({},J.defaultOptions()),{registrar:i}),J.stripUndefinedProperties(t)),this.options.extraContactHeaderParams=(this.options.extraContactHeaderParams||[]).slice(),this.options.extraHeaders=(this.options.extraHeaders||[]).slice(),!this.options.registrar)throw new Error("Registrar undefined.");if(this.options.registrar=this.options.registrar.clone(),this.options.regId&&!this.options.instanceId?this.options.instanceId=this.userAgent.instanceId:!this.options.regId&&this.options.instanceId&&(this.options.regId=1),this.options.instanceId&&P.parse(this.options.instanceId,"uuid")===-1)throw new Error("Invalid instanceId.");if(this.options.regId&&this.options.regId<0)throw new Error("Invalid regId.");const s=this.options.registrar,r=this.options.params&&this.options.params.fromUri||e.userAgentCore.configuration.aor,n=this.options.params&&this.options.params.toUri||e.configuration.uri,o=this.options.params||{},d=(t.extraHeaders||[]).slice();if(this.request=e.userAgentCore.makeOutgoingRequestMessage(v.REGISTER,s,r,n,o,d,void 0),this.expires=this.options.expires||J.defaultExpires,this.expires<0)throw new Error("Invalid expires.");if(this.refreshFrequency=this.options.refreshFrequency||J.defaultRefreshFrequency,this.refreshFrequency<50||this.refreshFrequency>99)throw new Error("Invalid refresh frequency. The value represents a percentage of the expiration time and should be between 50 and 99.");this.logger=e.getLogger("sip.Registerer"),this.options.logConfiguration&&(this.logger.log("Configuration:"),Object.keys(this.options).forEach(u=>{const h=this.options[u];u==="registrar"?this.logger.log("· "+u+": "+h):this.logger.log("· "+u+": "+JSON.stringify(h))})),this.id=this.request.callId+this.request.from.parameters.tag,this.userAgent._registerers[this.id]=this}static defaultOptions(){return{expires:J.defaultExpires,extraContactHeaderParams:[],extraHeaders:[],logConfiguration:!0,instanceId:"",params:{},regId:0,registrar:new z("sip","anonymous","anonymous.invalid"),refreshFrequency:J.defaultRefreshFrequency}}static stripUndefinedProperties(e){return Object.keys(e).reduce((t,i)=>(e[i]!==void 0&&(t[i]=e[i]),t),{})}get contacts(){return this._contacts.slice()}get retryAfter(){return this._retryAfter}get state(){return this._state}get stateChange(){return this._stateEventEmitter}dispose(){return this.disposed?Promise.resolve():(this.disposed=!0,this.logger.log(`Registerer ${this.id} in state ${this.state} is being disposed`),delete this.userAgent._registerers[this.id],new Promise(e=>{const t=()=>{if(!this.waiting&&this._state===R.Registered){this.stateChange.addListener(()=>{this.terminated(),e()},{once:!0}),this.unregister();return}this.terminated(),e()};this.waiting?this.waitingChange.addListener(()=>{t()},{once:!0}):t()}))}register(e={}){if(this.state===R.Terminated)throw this.stateError(),new Error("Registerer terminated. Unable to register.");if(this.disposed)throw this.stateError(),new Error("Registerer disposed. Unable to register.");if(this.waiting){this.waitingWarning();const s=new ve("REGISTER request already in progress, waiting for final response");return Promise.reject(s)}e.requestOptions&&(this.options=Object.assign(Object.assign({},this.options),e.requestOptions));const t=(this.options.extraHeaders||[]).slice();t.push("Contact: "+this.generateContactHeader(this.expires)),t.push("Allow: "+["ACK","CANCEL","INVITE","MESSAGE","BYE","OPTIONS","INFO","NOTIFY","REFER"].toString()),this.request.cseq++,this.request.setHeader("cseq",this.request.cseq+" REGISTER"),this.request.extraHeaders=t,this.waitingToggle(!0);const i=this.userAgent.userAgentCore.register(this.request,{onAccept:s=>{let r;s.message.hasHeader("expires")&&(r=Number(s.message.getHeader("expires"))),this._contacts=s.message.getHeaders("contact");let n=this._contacts.length;if(!n){this.logger.error("No Contact header in response to REGISTER, dropping response."),this.unregistered();return}let o;for(;n--;){if(o=s.message.parseHeader("contact",n),!o)throw new Error("Contact undefined");if(this.userAgent.contact.pubGruu&&st(o.uri,this.userAgent.contact.pubGruu)){r=Number(o.getParam("expires"));break}if(this.userAgent.configuration.contactName===""){if(o.uri.user===this.userAgent.contact.uri.user){r=Number(o.getParam("expires"));break}}else if(st(o.uri,this.userAgent.contact.uri)){r=Number(o.getParam("expires"));break}o=void 0}if(o===void 0){this.logger.error("No Contact header pointing to us, dropping response"),this.unregistered(),this.waitingToggle(!1);return}if(r===void 0){this.logger.error("Contact pointing to us is missing expires parameter, dropping response"),this.unregistered(),this.waitingToggle(!1);return}if(o.hasParam("temp-gruu")){const d=o.getParam("temp-gruu");d&&(this.userAgent.contact.tempGruu=P.URIParse(d.replace(/"/g,"")))}if(o.hasParam("pub-gruu")){const d=o.getParam("pub-gruu");d&&(this.userAgent.contact.pubGruu=P.URIParse(d.replace(/"/g,"")))}this.registered(r),e.requestDelegate&&e.requestDelegate.onAccept&&e.requestDelegate.onAccept(s),this.waitingToggle(!1)},onProgress:s=>{e.requestDelegate&&e.requestDelegate.onProgress&&e.requestDelegate.onProgress(s)},onRedirect:s=>{this.logger.error("Redirect received. Not supported."),this.unregistered(),e.requestDelegate&&e.requestDelegate.onRedirect&&e.requestDelegate.onRedirect(s),this.waitingToggle(!1)},onReject:s=>{if(s.message.statusCode===423){if(!s.message.hasHeader("min-expires")){this.logger.error("423 response received for REGISTER without Min-Expires, dropping response"),this.unregistered(),this.waitingToggle(!1);return}this.expires=Number(s.message.getHeader("min-expires")),this.waitingToggle(!1),this.register();return}this.logger.warn(`Failed to register, status code ${s.message.statusCode}`);let r=NaN;if(s.message.statusCode===500||s.message.statusCode===503){const n=s.message.getHeader("retry-after");n&&(r=Number.parseInt(n,void 0))}this._retryAfter=isNaN(r)?void 0:r,this.unregistered(),e.requestDelegate&&e.requestDelegate.onReject&&e.requestDelegate.onReject(s),this._retryAfter=void 0,this.waitingToggle(!1)},onTrying:s=>{e.requestDelegate&&e.requestDelegate.onTrying&&e.requestDelegate.onTrying(s)}});return Promise.resolve(i)}unregister(e={}){if(this.state===R.Terminated)throw this.stateError(),new Error("Registerer terminated. Unable to register.");if(this.disposed&&this.state!==R.Registered)throw this.stateError(),new Error("Registerer disposed. Unable to register.");if(this.waiting){this.waitingWarning();const s=new ve("REGISTER request already in progress, waiting for final response");return Promise.reject(s)}this._state!==R.Registered&&!e.all&&this.logger.warn("Not currently registered, but sending an unregister anyway.");const t=(e.requestOptions&&e.requestOptions.extraHeaders||[]).slice();this.request.extraHeaders=t,e.all?(t.push("Contact: *"),t.push("Expires: 0")):t.push("Contact: "+this.generateContactHeader(0)),this.request.cseq++,this.request.setHeader("cseq",this.request.cseq+" REGISTER"),this.registrationTimer!==void 0&&(clearTimeout(this.registrationTimer),this.registrationTimer=void 0),this.waitingToggle(!0);const i=this.userAgent.userAgentCore.register(this.request,{onAccept:s=>{this._contacts=s.message.getHeaders("contact"),this.unregistered(),e.requestDelegate&&e.requestDelegate.onAccept&&e.requestDelegate.onAccept(s),this.waitingToggle(!1)},onProgress:s=>{e.requestDelegate&&e.requestDelegate.onProgress&&e.requestDelegate.onProgress(s)},onRedirect:s=>{this.logger.error("Unregister redirected. Not currently supported."),this.unregistered(),e.requestDelegate&&e.requestDelegate.onRedirect&&e.requestDelegate.onRedirect(s),this.waitingToggle(!1)},onReject:s=>{this.logger.error(`Unregister rejected with status code ${s.message.statusCode}`),this.unregistered(),e.requestDelegate&&e.requestDelegate.onReject&&e.requestDelegate.onReject(s),this.waitingToggle(!1)},onTrying:s=>{e.requestDelegate&&e.requestDelegate.onTrying&&e.requestDelegate.onTrying(s)}});return Promise.resolve(i)}clearTimers(){this.registrationTimer!==void 0&&(clearTimeout(this.registrationTimer),this.registrationTimer=void 0),this.registrationExpiredTimer!==void 0&&(clearTimeout(this.registrationExpiredTimer),this.registrationExpiredTimer=void 0)}generateContactHeader(e){let t=this.userAgent.contact.toString({register:!0});return this.options.regId&&this.options.instanceId&&(t+=";reg-id="+this.options.regId,t+=';+sip.instance="<urn:uuid:'+this.options.instanceId+'>"'),this.options.extraContactHeaderParams&&this.options.extraContactHeaderParams.forEach(i=>{t+=";"+i}),t+=";expires="+e,t}registered(e){this.clearTimers(),this.registrationTimer=setTimeout(()=>{this.registrationTimer=void 0,this.register()},this.refreshFrequency/100*e*1e3),this.registrationExpiredTimer=setTimeout(()=>{this.logger.warn("Registration expired"),this.unregistered()},e*1e3),this._state!==R.Registered&&this.stateTransition(R.Registered)}unregistered(){this.clearTimers(),this._state!==R.Unregistered&&this.stateTransition(R.Unregistered)}terminated(){this.clearTimers(),this._state!==R.Terminated&&this.stateTransition(R.Terminated)}stateTransition(e){const t=()=>{throw new Error(`Invalid state transition from ${this._state} to ${e}`)};switch(this._state){case R.Initial:e!==R.Registered&&e!==R.Unregistered&&e!==R.Terminated&&t();break;case R.Registered:e!==R.Unregistered&&e!==R.Terminated&&t();break;case R.Unregistered:e!==R.Registered&&e!==R.Terminated&&t();break;case R.Terminated:t();break;default:throw new Error("Unrecognized state.")}this._state=e,this.logger.log(`Registration transitioned to state ${this._state}`),this._stateEventEmitter.emit(this._state),e===R.Terminated&&this.dispose()}get waiting(){return this._waiting}get waitingChange(){return this._waitingEventEmitter}waitingToggle(e){if(this._waiting===e)throw new Error(`Invalid waiting transition from ${this._waiting} to ${e}`);this._waiting=e,this.logger.log(`Waiting toggled to ${this._waiting}`),this._waitingEventEmitter.emit(this._waiting)}waitingWarning(){let e="An attempt was made to send a REGISTER request while a prior one was still in progress.";e+=" RFC 3261 requires UAs MUST NOT send a new registration until they have received a final response",e+=" from the registrar for the previous one or the previous REGISTER request has timed out.",e+=" Note that if the transport disconnects, you still must wait for the prior request to time out before",e+=" sending a new REGISTER request or alternatively dispose of the current Registerer and create a new Registerer.",this.logger.warn(e)}stateError(){let t=`An attempt was made to send a REGISTER request when the Registerer ${this.state===R.Terminated?"is in 'Terminated' state":"has been disposed"}.`;t+=" The Registerer transitions to 'Terminated' when Registerer.dispose() is called.",t+=" Perhaps you called UserAgent.stop() which dipsoses of all Registerers?",this.logger.error(t)}}J.defaultExpires=600,J.defaultRefreshFrequency=99;var I;(function(a){a.Initial="Initial",a.NotifyWait="NotifyWait",a.Pending="Pending",a.Active="Active",a.Terminated="Terminated"})(I=I||(I={}));var T;(function(a){a.Connecting="Connecting",a.Connected="Connected",a.Disconnecting="Disconnecting",a.Disconnected="Disconnected"})(T=T||(T={}));var k;(function(a){a.Started="Started",a.Stopped="Stopped"})(k=k||(k={}));class H{constructor(){this._dataLength=0,this._bufferLength=0,this._state=new Int32Array(4),this._buffer=new ArrayBuffer(68),this._buffer8=new Uint8Array(this._buffer,0,68),this._buffer32=new Uint32Array(this._buffer,0,17),this.start()}static hashStr(e,t=!1){return this.onePassHasher.start().appendStr(e).end(t)}static hashAsciiStr(e,t=!1){return this.onePassHasher.start().appendAsciiStr(e).end(t)}static _hex(e){const t=H.hexChars,i=H.hexOut;let s,r,n,o;for(o=0;o<4;o+=1)for(r=o*8,s=e[o],n=0;n<8;n+=2)i[r+1+n]=t.charAt(s&15),s>>>=4,i[r+0+n]=t.charAt(s&15),s>>>=4;return i.join("")}static _md5cycle(e,t){let i=e[0],s=e[1],r=e[2],n=e[3];i+=(s&r|~s&n)+t[0]-680876936|0,i=(i<<7|i>>>25)+s|0,n+=(i&s|~i&r)+t[1]-389564586|0,n=(n<<12|n>>>20)+i|0,r+=(n&i|~n&s)+t[2]+606105819|0,r=(r<<17|r>>>15)+n|0,s+=(r&n|~r&i)+t[3]-1044525330|0,s=(s<<22|s>>>10)+r|0,i+=(s&r|~s&n)+t[4]-176418897|0,i=(i<<7|i>>>25)+s|0,n+=(i&s|~i&r)+t[5]+1200080426|0,n=(n<<12|n>>>20)+i|0,r+=(n&i|~n&s)+t[6]-1473231341|0,r=(r<<17|r>>>15)+n|0,s+=(r&n|~r&i)+t[7]-45705983|0,s=(s<<22|s>>>10)+r|0,i+=(s&r|~s&n)+t[8]+1770035416|0,i=(i<<7|i>>>25)+s|0,n+=(i&s|~i&r)+t[9]-1958414417|0,n=(n<<12|n>>>20)+i|0,r+=(n&i|~n&s)+t[10]-42063|0,r=(r<<17|r>>>15)+n|0,s+=(r&n|~r&i)+t[11]-1990404162|0,s=(s<<22|s>>>10)+r|0,i+=(s&r|~s&n)+t[12]+1804603682|0,i=(i<<7|i>>>25)+s|0,n+=(i&s|~i&r)+t[13]-40341101|0,n=(n<<12|n>>>20)+i|0,r+=(n&i|~n&s)+t[14]-1502002290|0,r=(r<<17|r>>>15)+n|0,s+=(r&n|~r&i)+t[15]+1236535329|0,s=(s<<22|s>>>10)+r|0,i+=(s&n|r&~n)+t[1]-165796510|0,i=(i<<5|i>>>27)+s|0,n+=(i&r|s&~r)+t[6]-1069501632|0,n=(n<<9|n>>>23)+i|0,r+=(n&s|i&~s)+t[11]+643717713|0,r=(r<<14|r>>>18)+n|0,s+=(r&i|n&~i)+t[0]-373897302|0,s=(s<<20|s>>>12)+r|0,i+=(s&n|r&~n)+t[5]-701558691|0,i=(i<<5|i>>>27)+s|0,n+=(i&r|s&~r)+t[10]+38016083|0,n=(n<<9|n>>>23)+i|0,r+=(n&s|i&~s)+t[15]-660478335|0,r=(r<<14|r>>>18)+n|0,s+=(r&i|n&~i)+t[4]-405537848|0,s=(s<<20|s>>>12)+r|0,i+=(s&n|r&~n)+t[9]+568446438|0,i=(i<<5|i>>>27)+s|0,n+=(i&r|s&~r)+t[14]-1019803690|0,n=(n<<9|n>>>23)+i|0,r+=(n&s|i&~s)+t[3]-187363961|0,r=(r<<14|r>>>18)+n|0,s+=(r&i|n&~i)+t[8]+1163531501|0,s=(s<<20|s>>>12)+r|0,i+=(s&n|r&~n)+t[13]-1444681467|0,i=(i<<5|i>>>27)+s|0,n+=(i&r|s&~r)+t[2]-51403784|0,n=(n<<9|n>>>23)+i|0,r+=(n&s|i&~s)+t[7]+1735328473|0,r=(r<<14|r>>>18)+n|0,s+=(r&i|n&~i)+t[12]-1926607734|0,s=(s<<20|s>>>12)+r|0,i+=(s^r^n)+t[5]-378558|0,i=(i<<4|i>>>28)+s|0,n+=(i^s^r)+t[8]-2022574463|0,n=(n<<11|n>>>21)+i|0,r+=(n^i^s)+t[11]+1839030562|0,r=(r<<16|r>>>16)+n|0,s+=(r^n^i)+t[14]-35309556|0,s=(s<<23|s>>>9)+r|0,i+=(s^r^n)+t[1]-1530992060|0,i=(i<<4|i>>>28)+s|0,n+=(i^s^r)+t[4]+1272893353|0,n=(n<<11|n>>>21)+i|0,r+=(n^i^s)+t[7]-155497632|0,r=(r<<16|r>>>16)+n|0,s+=(r^n^i)+t[10]-1094730640|0,s=(s<<23|s>>>9)+r|0,i+=(s^r^n)+t[13]+681279174|0,i=(i<<4|i>>>28)+s|0,n+=(i^s^r)+t[0]-358537222|0,n=(n<<11|n>>>21)+i|0,r+=(n^i^s)+t[3]-722521979|0,r=(r<<16|r>>>16)+n|0,s+=(r^n^i)+t[6]+76029189|0,s=(s<<23|s>>>9)+r|0,i+=(s^r^n)+t[9]-640364487|0,i=(i<<4|i>>>28)+s|0,n+=(i^s^r)+t[12]-421815835|0,n=(n<<11|n>>>21)+i|0,r+=(n^i^s)+t[15]+530742520|0,r=(r<<16|r>>>16)+n|0,s+=(r^n^i)+t[2]-995338651|0,s=(s<<23|s>>>9)+r|0,i+=(r^(s|~n))+t[0]-198630844|0,i=(i<<6|i>>>26)+s|0,n+=(s^(i|~r))+t[7]+1126891415|0,n=(n<<10|n>>>22)+i|0,r+=(i^(n|~s))+t[14]-1416354905|0,r=(r<<15|r>>>17)+n|0,s+=(n^(r|~i))+t[5]-57434055|0,s=(s<<21|s>>>11)+r|0,i+=(r^(s|~n))+t[12]+1700485571|0,i=(i<<6|i>>>26)+s|0,n+=(s^(i|~r))+t[3]-1894986606|0,n=(n<<10|n>>>22)+i|0,r+=(i^(n|~s))+t[10]-1051523|0,r=(r<<15|r>>>17)+n|0,s+=(n^(r|~i))+t[1]-2054922799|0,s=(s<<21|s>>>11)+r|0,i+=(r^(s|~n))+t[8]+1873313359|0,i=(i<<6|i>>>26)+s|0,n+=(s^(i|~r))+t[15]-30611744|0,n=(n<<10|n>>>22)+i|0,r+=(i^(n|~s))+t[6]-1560198380|0,r=(r<<15|r>>>17)+n|0,s+=(n^(r|~i))+t[13]+1309151649|0,s=(s<<21|s>>>11)+r|0,i+=(r^(s|~n))+t[4]-145523070|0,i=(i<<6|i>>>26)+s|0,n+=(s^(i|~r))+t[11]-1120210379|0,n=(n<<10|n>>>22)+i|0,r+=(i^(n|~s))+t[2]+718787259|0,r=(r<<15|r>>>17)+n|0,s+=(n^(r|~i))+t[9]-343485551|0,s=(s<<21|s>>>11)+r|0,e[0]=i+e[0]|0,e[1]=s+e[1]|0,e[2]=r+e[2]|0,e[3]=n+e[3]|0}start(){return this._dataLength=0,this._bufferLength=0,this._state.set(H.stateIdentity),this}appendStr(e){const t=this._buffer8,i=this._buffer32;let s=this._bufferLength,r,n;for(n=0;n<e.length;n+=1){if(r=e.charCodeAt(n),r<128)t[s++]=r;else if(r<2048)t[s++]=(r>>>6)+192,t[s++]=r&63|128;else if(r<55296||r>56319)t[s++]=(r>>>12)+224,t[s++]=r>>>6&63|128,t[s++]=r&63|128;else{if(r=(r-55296)*1024+(e.charCodeAt(++n)-56320)+65536,r>1114111)throw new Error("Unicode standard supports code points up to U+10FFFF");t[s++]=(r>>>18)+240,t[s++]=r>>>12&63|128,t[s++]=r>>>6&63|128,t[s++]=r&63|128}s>=64&&(this._dataLength+=64,H._md5cycle(this._state,i),s-=64,i[0]=i[16])}return this._bufferLength=s,this}appendAsciiStr(e){const t=this._buffer8,i=this._buffer32;let s=this._bufferLength,r,n=0;for(;;){for(r=Math.min(e.length-n,64-s);r--;)t[s++]=e.charCodeAt(n++);if(s<64)break;this._dataLength+=64,H._md5cycle(this._state,i),s=0}return this._bufferLength=s,this}appendByteArray(e){const t=this._buffer8,i=this._buffer32;let s=this._bufferLength,r,n=0;for(;;){for(r=Math.min(e.length-n,64-s);r--;)t[s++]=e[n++];if(s<64)break;this._dataLength+=64,H._md5cycle(this._state,i),s=0}return this._bufferLength=s,this}getState(){const e=this,t=e._state;return{buffer:String.fromCharCode.apply(null,e._buffer8),buflen:e._bufferLength,length:e._dataLength,state:[t[0],t[1],t[2],t[3]]}}setState(e){const t=e.buffer,i=e.state,s=this._state;let r;for(this._dataLength=e.length,this._bufferLength=e.buflen,s[0]=i[0],s[1]=i[1],s[2]=i[2],s[3]=i[3],r=0;r<t.length;r+=1)this._buffer8[r]=t.charCodeAt(r)}end(e=!1){const t=this._bufferLength,i=this._buffer8,s=this._buffer32,r=(t>>2)+1;let n;if(this._dataLength+=t,i[t]=128,i[t+1]=i[t+2]=i[t+3]=0,s.set(H.buffer32Identity.subarray(r),r),t>55&&(H._md5cycle(this._state,s),s.set(H.buffer32Identity)),n=this._dataLength*8,n<=4294967295)s[14]=n;else{const o=n.toString(16).match(/(.*?)(.{0,8})$/);if(o===null)return;const d=parseInt(o[2],16),u=parseInt(o[1],16)||0;s[14]=d,s[15]=u}return H._md5cycle(this._state,s),e?this._state:H._hex(this._state)}}H.stateIdentity=new Int32Array([1732584193,-271733879,-1732584194,271733878]),H.buffer32Identity=new Int32Array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),H.hexChars="0123456789abcdef",H.hexOut=[],H.onePassHasher=new H,H.hashStr("hello")!=="5d41402abc4b2a76b9719d911017c592"&&console.error("Md5 self test failed.");function oe(a){return H.hashStr(a)}class Gt{constructor(e,t,i,s){this.logger=e.getLogger("sipjs.digestauthentication"),this.username=i,this.password=s,this.ha1=t,this.nc=0,this.ncHex="00000000"}authenticate(e,t,i){if(this.algorithm=t.algorithm,this.realm=t.realm,this.nonce=t.nonce,this.opaque=t.opaque,this.stale=t.stale,this.algorithm){if(this.algorithm!=="MD5")return this.logger.warn("challenge with Digest algorithm different than 'MD5', authentication aborted"),!1}else this.algorithm="MD5";if(!this.realm)return this.logger.warn("challenge without Digest realm, authentication aborted"),!1;if(!this.nonce)return this.logger.warn("challenge without Digest nonce, authentication aborted"),!1;if(t.qop)if(t.qop.indexOf("auth")>-1)this.qop="auth";else if(t.qop.indexOf("auth-int")>-1)this.qop="auth-int";else return this.logger.warn("challenge without Digest qop different than 'auth' or 'auth-int', authentication aborted"),!1;else this.qop=void 0;return this.method=e.method,this.uri=e.ruri,this.cnonce=ue(12),this.nc+=1,this.updateNcHex(),this.nc===4294967296&&(this.nc=1,this.ncHex="00000001"),this.calculateResponse(i),!0}toString(){const e=[];if(!this.response)throw new Error("response field does not exist, cannot generate Authorization header");return e.push("algorithm="+this.algorithm),e.push('username="'+this.username+'"'),e.push('realm="'+this.realm+'"'),e.push('nonce="'+this.nonce+'"'),e.push('uri="'+this.uri+'"'),e.push('response="'+this.response+'"'),this.opaque&&e.push('opaque="'+this.opaque+'"'),this.qop&&(e.push("qop="+this.qop),e.push('cnonce="'+this.cnonce+'"'),e.push("nc="+this.ncHex)),"Digest "+e.join(", ")}updateNcHex(){const e=Number(this.nc).toString(16);this.ncHex="00000000".substr(0,8-e.length)+e}calculateResponse(e){let t,i;t=this.ha1,(t===""||t===void 0)&&(t=oe(this.username+":"+this.realm+":"+this.password)),this.qop==="auth"?(i=oe(this.method+":"+this.uri),this.response=oe(t+":"+this.nonce+":"+this.ncHex+":"+this.cnonce+":auth:"+i)):this.qop==="auth-int"?(i=oe(this.method+":"+this.uri+":"+oe(e||"")),this.response=oe(t+":"+this.nonce+":"+this.ncHex+":"+this.cnonce+":auth-int:"+i)):this.qop===void 0&&(i=oe(this.method+":"+this.uri),this.response=oe(t+":"+this.nonce+":"+i))}}var q;(function(a){a[a.error=0]="error",a[a.warn=1]="warn",a[a.log=2]="log",a[a.debug=3]="debug"})(q=q||(q={}));class dt{constructor(e,t,i){this.logger=e,this.category=t,this.label=i}error(e){this.genericLog(q.error,e)}warn(e){this.genericLog(q.warn,e)}log(e){this.genericLog(q.log,e)}debug(e){this.genericLog(q.debug,e)}genericLog(e,t){this.logger.genericLog(e,this.category,this.label,t)}get level(){return this.logger.level}set level(e){this.logger.level=e}}class Wt{constructor(){this.builtinEnabled=!0,this._level=q.log,this.loggers={},this.logger=this.getLogger("sip:loggerfactory")}get level(){return this._level}set level(e){e>=0&&e<=3?this._level=e:e>3?this._level=3:q.hasOwnProperty(e)?this._level=e:this.logger.error("invalid 'level' parameter value: "+JSON.stringify(e))}get connector(){return this._connector}set connector(e){e?typeof e=="function"?this._connector=e:this.logger.error("invalid 'connector' parameter value: "+JSON.stringify(e)):this._connector=void 0}getLogger(e,t){if(t&&this.level===3)return new dt(this,e,t);if(this.loggers[e])return this.loggers[e];{const i=new dt(this,e);return this.loggers[e]=i,i}}genericLog(e,t,i,s){this.level>=e&&this.builtinEnabled&&this.print(e,t,i,s),this.connector&&this.connector(q[e],t,i,s)}print(e,t,i,s){if(typeof s=="string"){const r=[new Date,t];i&&r.push(i),s=r.concat(s).join(" | ")}switch(e){case q.error:console.error(s);break;case q.warn:console.warn(s);break;case q.log:console.log(s);break;case q.debug:console.debug(s);break}}}var ke;(function(a){function e(s,r){let n=r,o=0,d=0;if(s.substring(n,n+2).match(/(^\r\n)/))return-2;for(;o===0;){if(d=s.indexOf(`\r
|
|
23
|
+
`,n),d===-1)return d;!s.substring(d+2,d+4).match(/(^\r\n)/)&&s.charAt(d+2).match(/(^\s+)/)?n=d+2:o=d}return o}a.getHeader=e;function t(s,r,n,o){const d=r.indexOf(":",n),u=r.substring(n,d).trim(),h=r.substring(d+1,o).trim();let m;switch(u.toLowerCase()){case"via":case"v":s.addHeader("via",h),s.getHeaders("via").length===1?(m=s.parseHeader("Via"),m&&(s.via=m,s.viaBranch=m.branch)):m=0;break;case"from":case"f":s.setHeader("from",h),m=s.parseHeader("from"),m&&(s.from=m,s.fromTag=m.getParam("tag"));break;case"to":case"t":s.setHeader("to",h),m=s.parseHeader("to"),m&&(s.to=m,s.toTag=m.getParam("tag"));break;case"record-route":if(m=P.parse(h,"Record_Route"),m===-1){m=void 0;break}if(!(m instanceof Array)){m=void 0;break}m.forEach(S=>{s.addHeader("record-route",h.substring(S.position,S.offset)),s.headers["Record-Route"][s.getHeaders("record-route").length-1].parsed=S.parsed});break;case"call-id":case"i":s.setHeader("call-id",h),m=s.parseHeader("call-id"),m&&(s.callId=h);break;case"contact":case"m":if(m=P.parse(h,"Contact"),m===-1){m=void 0;break}if(!(m instanceof Array)){m=void 0;break}m.forEach(S=>{s.addHeader("contact",h.substring(S.position,S.offset)),s.headers.Contact[s.getHeaders("contact").length-1].parsed=S.parsed});break;case"content-length":case"l":s.setHeader("content-length",h),m=s.parseHeader("content-length");break;case"content-type":case"c":s.setHeader("content-type",h),m=s.parseHeader("content-type");break;case"cseq":s.setHeader("cseq",h),m=s.parseHeader("cseq"),m&&(s.cseq=m.value),s instanceof re&&(s.method=m.method);break;case"max-forwards":s.setHeader("max-forwards",h),m=s.parseHeader("max-forwards");break;case"www-authenticate":s.setHeader("www-authenticate",h),m=s.parseHeader("www-authenticate");break;case"proxy-authenticate":s.setHeader("proxy-authenticate",h),m=s.parseHeader("proxy-authenticate");break;case"refer-to":case"r":s.setHeader("refer-to",h),m=s.parseHeader("refer-to"),m&&(s.referTo=m);break;default:s.addHeader(u.toLowerCase(),h),m=0}return m===void 0?{error:"error parsing header '"+u+"'"}:!0}a.parseHeader=t;function i(s,r){let n=0,o=s.indexOf(`\r
|
|
24
|
+
`);if(o===-1){r.warn("no CRLF found, not a SIP message, discarded");return}const d=s.substring(0,o),u=P.parse(d,"Request_Response");let h;if(u===-1){r.warn('error parsing first line of SIP message: "'+d+'"');return}else u.status_code?(h=new re,h.statusCode=u.status_code,h.reasonPhrase=u.reason_phrase):(h=new me,h.method=u.method,h.ruri=u.uri);h.data=s,n=o+2;let m;for(;;){if(o=e(s,n),o===-2){m=n+2;break}else if(o===-1){r.error("malformed message");return}const S=t(h,s,n,o);if(S&&S!==!0){r.error(S.error);return}n=o+2}return h.hasHeader("content-length")?h.body=s.substr(m,Number(h.getHeader("content-length"))):h.body=s.substring(m),h}a.parseMessage=i})(ke=ke||(ke={}));function lt(a,e){if(e.statusCode<100||e.statusCode>699)throw new TypeError("Invalid statusCode: "+e.statusCode);const i=e.reasonPhrase?e.reasonPhrase:Ae(e.statusCode);let s="SIP/2.0 "+e.statusCode+" "+i+`\r
|
|
25
|
+
`;e.statusCode>=100&&e.statusCode<200,e.statusCode;const r="From: "+a.getHeader("From")+`\r
|
|
26
|
+
`,n="Call-ID: "+a.callId+`\r
|
|
27
|
+
`,o="CSeq: "+a.cseq+" "+a.method+`\r
|
|
28
|
+
`,d=a.getHeaders("via").reduce((x,_)=>x+"Via: "+_+`\r
|
|
29
|
+
`,"");let u="To: "+a.getHeader("to");if(e.statusCode>100&&!a.parseHeader("to").hasParam("tag")){let x=e.toTag;x||(x=$e()),u+=";tag="+x}u+=`\r
|
|
30
30
|
`;let h="";e.supported&&(h="Supported: "+e.supported.join(", ")+`\r
|
|
31
|
-
`);let
|
|
32
|
-
`);let S="";return e.extraHeaders&&(S=e.extraHeaders.reduce((x,
|
|
33
|
-
`,"")),s+=d,s+=r,s+=
|
|
34
|
-
`,s+="Content-Length: "+
|
|
31
|
+
`);let m="";e.userAgent&&(m="User-Agent: "+e.userAgent+`\r
|
|
32
|
+
`);let S="";return e.extraHeaders&&(S=e.extraHeaders.reduce((x,_)=>x+_.trim()+`\r
|
|
33
|
+
`,"")),s+=d,s+=r,s+=u,s+=o,s+=n,s+=h,s+=m,s+=S,e.body?(s+="Content-Type: "+e.body.contentType+`\r
|
|
34
|
+
`,s+="Content-Length: "+Ce(e.body.content)+`\r
|
|
35
35
|
\r
|
|
36
36
|
`,s+=e.body.content):s+=`Content-Length: 0\r
|
|
37
37
|
\r
|
|
38
|
-
`,{message:s}}class je extends de{constructor(e){super(e||"Unspecified transport error.")}}class lt{constructor(e,t,i,s,r){this._transport=e,this._user=t,this._id=i,this._state=s,this.listeners=new Array,this.logger=t.loggerFactory.getLogger(r,i),this.logger.debug(`Constructing ${this.typeToString()} with id ${this.id}.`)}dispose(){this.logger.debug(`Destroyed ${this.typeToString()} with id ${this.id}.`)}get id(){return this._id}get kind(){throw new Error("Invalid kind.")}get state(){return this._state}get transport(){return this._transport}addStateChangeListener(e,t){const i=()=>{this.removeStateChangeListener(i),e()};t?.once===!0?this.listeners.push(i):this.listeners.push(e)}notifyStateChangeListeners(){this.listeners.slice().forEach(e=>e())}removeStateChangeListener(e){this.listeners=this.listeners.filter(t=>t!==e)}logTransportError(e,t){this.logger.error(e.message),this.logger.error(`Transport error occurred in ${this.typeToString()} with id ${this.id}.`),this.logger.error(t)}send(e){return this.transport.send(e).catch(t=>{if(t instanceof je)throw this.onTransportError(t),t;let i;throw t&&typeof t.message=="string"?i=new je(t.message):i=new je,this.onTransportError(i),i})}setState(e){this.logger.debug(`State change to "${e}" on ${this.typeToString()} with id ${this.id}.`),this._state=e,this._user.onStateChange&&this._user.onStateChange(e),this.notifyStateChangeListeners()}typeToString(){return"UnknownType"}}class ht extends lt{constructor(e,t,i,s,r){super(t,i,e.viaBranch,s,r),this._request=e,this.user=i}get request(){return this._request}}var g;(function(o){o.Accepted="Accepted",o.Calling="Calling",o.Completed="Completed",o.Confirmed="Confirmed",o.Proceeding="Proceeding",o.Terminated="Terminated",o.Trying="Trying"})(g=g||(g={}));class U extends ht{constructor(e,t,i){super(e,t,i,g.Proceeding,"sip.transaction.ist")}dispose(){this.stopProgressExtensionTimer(),this.H&&(clearTimeout(this.H),this.H=void 0),this.I&&(clearTimeout(this.I),this.I=void 0),this.L&&(clearTimeout(this.L),this.L=void 0),super.dispose()}get kind(){return"ist"}receiveRequest(e){switch(this.state){case g.Proceeding:if(e.method===v.INVITE){this.lastProvisionalResponse&&this.send(this.lastProvisionalResponse).catch(i=>{this.logTransportError(i,"Failed to send retransmission of provisional response.")});return}break;case g.Accepted:if(e.method===v.INVITE)return;break;case g.Completed:if(e.method===v.INVITE){if(!this.lastFinalResponse)throw new Error("Last final response undefined.");this.send(this.lastFinalResponse).catch(i=>{this.logTransportError(i,"Failed to send retransmission of final response.")});return}if(e.method===v.ACK){this.stateTransition(g.Confirmed);return}break;case g.Confirmed:if(e.method===v.INVITE||e.method===v.ACK)return;break;case g.Terminated:if(e.method===v.INVITE||e.method===v.ACK)return;break;default:throw new Error(`Invalid state ${this.state}`)}const t=`INVITE server transaction received unexpected ${e.method} request while in state ${this.state}.`;this.logger.warn(t)}receiveResponse(e,t){if(e<100||e>699)throw new Error(`Invalid status code ${e}`);switch(this.state){case g.Proceeding:if(e>=100&&e<=199){this.lastProvisionalResponse=t,e>100&&this.startProgressExtensionTimer(),this.send(t).catch(s=>{this.logTransportError(s,"Failed to send 1xx response.")});return}if(e>=200&&e<=299){this.lastFinalResponse=t,this.stateTransition(g.Accepted),this.send(t).catch(s=>{this.logTransportError(s,"Failed to send 2xx response.")});return}if(e>=300&&e<=699){this.lastFinalResponse=t,this.stateTransition(g.Completed),this.send(t).catch(s=>{this.logTransportError(s,"Failed to send non-2xx final response.")});return}break;case g.Accepted:if(e>=200&&e<=299){this.send(t).catch(s=>{this.logTransportError(s,"Failed to send 2xx response.")});return}break;case g.Completed:break;case g.Confirmed:break;case g.Terminated:break;default:throw new Error(`Invalid state ${this.state}`)}const i=`INVITE server transaction received unexpected ${e} response from TU while in state ${this.state}.`;throw this.logger.error(i),new Error(i)}retransmitAcceptedResponse(){this.state===g.Accepted&&this.lastFinalResponse&&this.send(this.lastFinalResponse).catch(e=>{this.logTransportError(e,"Failed to send 2xx response.")})}onTransportError(e){this.user.onTransportError&&this.user.onTransportError(e)}typeToString(){return"INVITE server transaction"}stateTransition(e){const t=()=>{throw new Error(`Invalid state transition from ${this.state} to ${e}`)};switch(e){case g.Proceeding:t();break;case g.Accepted:case g.Completed:this.state!==g.Proceeding&&t();break;case g.Confirmed:this.state!==g.Completed&&t();break;case g.Terminated:this.state!==g.Accepted&&this.state!==g.Completed&&this.state!==g.Confirmed&&t();break;default:t()}this.stopProgressExtensionTimer(),e===g.Accepted&&(this.L=setTimeout(()=>this.timerL(),M.TIMER_L)),e===g.Completed&&(this.H=setTimeout(()=>this.timerH(),M.TIMER_H)),e===g.Confirmed&&(this.I=setTimeout(()=>this.timerI(),M.TIMER_I)),e===g.Terminated&&this.dispose(),this.setState(e)}startProgressExtensionTimer(){this.progressExtensionTimer===void 0&&(this.progressExtensionTimer=setInterval(()=>{if(this.logger.debug(`Progress extension timer expired for INVITE server transaction ${this.id}.`),!this.lastProvisionalResponse)throw new Error("Last provisional response undefined.");this.send(this.lastProvisionalResponse).catch(e=>{this.logTransportError(e,"Failed to send retransmission of provisional response.")})},M.PROVISIONAL_RESPONSE_INTERVAL))}stopProgressExtensionTimer(){this.progressExtensionTimer!==void 0&&(clearInterval(this.progressExtensionTimer),this.progressExtensionTimer=void 0)}timerG(){}timerH(){this.logger.debug(`Timer H expired for INVITE server transaction ${this.id}.`),this.state===g.Completed&&(this.logger.warn("ACK to negative final response was never received, terminating transaction."),this.stateTransition(g.Terminated))}timerI(){this.logger.debug(`Timer I expired for INVITE server transaction ${this.id}.`),this.stateTransition(g.Terminated)}timerL(){this.logger.debug(`Timer L expired for INVITE server transaction ${this.id}.`),this.state===g.Accepted&&this.stateTransition(g.Terminated)}}class Pe extends lt{constructor(e,t,i,s,r){super(t,i,Pe.makeId(e),s,r),this._request=e,this.user=i,e.setViaHeader(this.id,t.protocol)}static makeId(e){if(e.method==="CANCEL"){if(!e.branch)throw new Error("Outgoing CANCEL request without a branch.");return e.branch}else return"z9hG4bK"+Math.floor(Math.random()*1e7)}get request(){return this._request}onRequestTimeout(){this.user.onRequestTimeout&&this.user.onRequestTimeout()}}class B extends Pe{constructor(e,t,i){super(e,t,i,g.Trying,"sip.transaction.nict"),this.F=setTimeout(()=>this.timerF(),M.TIMER_F),this.send(e.toString()).catch(s=>{this.logTransportError(s,"Failed to send initial outgoing request.")})}dispose(){this.F&&(clearTimeout(this.F),this.F=void 0),this.K&&(clearTimeout(this.K),this.K=void 0),super.dispose()}get kind(){return"nict"}receiveResponse(e){const t=e.statusCode;if(!t||t<100||t>699)throw new Error(`Invalid status code ${t}`);switch(this.state){case g.Trying:if(t>=100&&t<=199){this.stateTransition(g.Proceeding),this.user.receiveResponse&&this.user.receiveResponse(e);return}if(t>=200&&t<=699){if(this.stateTransition(g.Completed),t===408){this.onRequestTimeout();return}this.user.receiveResponse&&this.user.receiveResponse(e);return}break;case g.Proceeding:if(t>=100&&t<=199&&this.user.receiveResponse)return this.user.receiveResponse(e);if(t>=200&&t<=699){if(this.stateTransition(g.Completed),t===408){this.onRequestTimeout();return}this.user.receiveResponse&&this.user.receiveResponse(e);return}break;case g.Completed:return;case g.Terminated:return;default:throw new Error(`Invalid state ${this.state}`)}const i=`Non-INVITE client transaction received unexpected ${t} response while in state ${this.state}.`;this.logger.warn(i)}onTransportError(e){this.user.onTransportError&&this.user.onTransportError(e),this.stateTransition(g.Terminated,!0)}typeToString(){return"non-INVITE client transaction"}stateTransition(e,t=!1){const i=()=>{throw new Error(`Invalid state transition from ${this.state} to ${e}`)};switch(e){case g.Trying:i();break;case g.Proceeding:this.state!==g.Trying&&i();break;case g.Completed:this.state!==g.Trying&&this.state!==g.Proceeding&&i();break;case g.Terminated:this.state!==g.Trying&&this.state!==g.Proceeding&&this.state!==g.Completed&&(t||i());break;default:i()}e===g.Completed&&(this.F&&(clearTimeout(this.F),this.F=void 0),this.K=setTimeout(()=>this.timerK(),M.TIMER_K)),e===g.Terminated&&this.dispose(),this.setState(e)}timerF(){this.logger.debug(`Timer F expired for non-INVITE client transaction ${this.id}.`),(this.state===g.Trying||this.state===g.Proceeding)&&(this.onRequestTimeout(),this.stateTransition(g.Terminated))}timerK(){this.state===g.Completed&&this.stateTransition(g.Terminated)}}class we{constructor(e,t){this.core=e,this.dialogState=t,this.core.dialogs.set(this.id,this)}static initialDialogStateForUserAgentClient(e,t){const s=t.getHeaders("record-route").reverse(),r=t.parseHeader("contact");if(!r)throw new Error("Contact undefined.");if(!(r instanceof N))throw new Error("Contact not instance of NameAddrHeader.");const n=r.uri,a=e.cseq,d=void 0,f=e.callId,h=e.fromTag,w=t.toTag;if(!f)throw new Error("Call id undefined.");if(!h)throw new Error("From tag undefined.");if(!w)throw new Error("To tag undefined.");if(!e.from)throw new Error("From undefined.");if(!e.to)throw new Error("To undefined.");const S=e.from.uri,x=e.to.uri;if(!t.statusCode)throw new Error("Incoming response status code undefined.");const I=t.statusCode<200;return{id:f+h+w,early:I,callId:f,localTag:h,remoteTag:w,localSequenceNumber:a,remoteSequenceNumber:d,localURI:S,remoteURI:x,remoteTarget:n,routeSet:s,secure:!1}}static initialDialogStateForUserAgentServer(e,t,i=!1){const r=e.getHeaders("record-route"),n=e.parseHeader("contact");if(!n)throw new Error("Contact undefined.");if(!(n instanceof N))throw new Error("Contact not instance of NameAddrHeader.");const a=n.uri,d=e.cseq,f=void 0,h=e.callId,w=t,S=e.fromTag,x=e.from.uri,I=e.to.uri;return{id:h+w+S,early:i,callId:h,localTag:w,remoteTag:S,localSequenceNumber:f,remoteSequenceNumber:d,localURI:I,remoteURI:x,remoteTarget:a,routeSet:r,secure:!1}}dispose(){this.core.dialogs.delete(this.id)}get id(){return this.dialogState.id}get early(){return this.dialogState.early}get callId(){return this.dialogState.callId}get localTag(){return this.dialogState.localTag}get remoteTag(){return this.dialogState.remoteTag}get localSequenceNumber(){return this.dialogState.localSequenceNumber}get remoteSequenceNumber(){return this.dialogState.remoteSequenceNumber}get localURI(){return this.dialogState.localURI}get remoteURI(){return this.dialogState.remoteURI}get remoteTarget(){return this.dialogState.remoteTarget}get routeSet(){return this.dialogState.routeSet}get secure(){return this.dialogState.secure}get userAgentCore(){return this.core}confirm(){this.dialogState.early=!1}receiveRequest(e){if(e.method!==v.ACK){if(this.remoteSequenceNumber){if(e.cseq<=this.remoteSequenceNumber)throw new Error("Out of sequence in dialog request. Did you forget to call sequenceGuard()?");this.dialogState.remoteSequenceNumber=e.cseq}this.remoteSequenceNumber||(this.dialogState.remoteSequenceNumber=e.cseq)}}recomputeRouteSet(e){this.dialogState.routeSet=e.getHeaders("record-route").reverse()}createOutgoingRequestMessage(e,t){const i=this.remoteURI,s=this.remoteTag,r=this.localURI,n=this.localTag,a=this.callId;let d;t&&t.cseq?d=t.cseq:this.dialogState.localSequenceNumber?d=this.dialogState.localSequenceNumber+=1:d=this.dialogState.localSequenceNumber=1;const f=this.remoteTarget,h=this.routeSet,w=t&&t.extraHeaders,S=t&&t.body;return this.userAgentCore.makeOutgoingRequestMessage(e,f,r,i,{callId:a,cseq:d,fromTag:n,toTag:s,routeSet:h},w,S)}incrementLocalSequenceNumber(){if(!this.dialogState.localSequenceNumber)throw new Error("Local sequence number undefined.");this.dialogState.localSequenceNumber+=1}sequenceGuard(e){return e.method===v.ACK?!0:this.remoteSequenceNumber&&e.cseq<=this.remoteSequenceNumber?(this.core.replyStateless(e,{statusCode:500}),!1):!0}}class ae extends Pe{constructor(e,t,i){super(e,t,i,g.Calling,"sip.transaction.ict"),this.ackRetransmissionCache=new Map,this.B=setTimeout(()=>this.timerB(),M.TIMER_B),this.send(e.toString()).catch(s=>{this.logTransportError(s,"Failed to send initial outgoing request.")})}dispose(){this.B&&(clearTimeout(this.B),this.B=void 0),this.D&&(clearTimeout(this.D),this.D=void 0),this.M&&(clearTimeout(this.M),this.M=void 0),super.dispose()}get kind(){return"ict"}ackResponse(e){const t=e.toTag;if(!t)throw new Error("To tag undefined.");const i="z9hG4bK"+Math.floor(Math.random()*1e7);e.setViaHeader(i,this.transport.protocol),this.ackRetransmissionCache.set(t,e),this.send(e.toString()).catch(s=>{this.logTransportError(s,"Failed to send ACK to 2xx response.")})}receiveResponse(e){const t=e.statusCode;if(!t||t<100||t>699)throw new Error(`Invalid status code ${t}`);switch(this.state){case g.Calling:if(t>=100&&t<=199){this.stateTransition(g.Proceeding),this.user.receiveResponse&&this.user.receiveResponse(e);return}if(t>=200&&t<=299){this.ackRetransmissionCache.set(e.toTag,void 0),this.stateTransition(g.Accepted),this.user.receiveResponse&&this.user.receiveResponse(e);return}if(t>=300&&t<=699){this.stateTransition(g.Completed),this.ack(e),this.user.receiveResponse&&this.user.receiveResponse(e);return}break;case g.Proceeding:if(t>=100&&t<=199){this.user.receiveResponse&&this.user.receiveResponse(e);return}if(t>=200&&t<=299){this.ackRetransmissionCache.set(e.toTag,void 0),this.stateTransition(g.Accepted),this.user.receiveResponse&&this.user.receiveResponse(e);return}if(t>=300&&t<=699){this.stateTransition(g.Completed),this.ack(e),this.user.receiveResponse&&this.user.receiveResponse(e);return}break;case g.Accepted:if(t>=200&&t<=299){if(!this.ackRetransmissionCache.has(e.toTag)){this.ackRetransmissionCache.set(e.toTag,void 0),this.user.receiveResponse&&this.user.receiveResponse(e);return}const s=this.ackRetransmissionCache.get(e.toTag);if(s){this.send(s.toString()).catch(r=>{this.logTransportError(r,"Failed to send retransmission of ACK to 2xx response.")});return}return}break;case g.Completed:if(t>=300&&t<=699){this.ack(e);return}break;case g.Terminated:break;default:throw new Error(`Invalid state ${this.state}`)}const i=`Received unexpected ${t} response while in state ${this.state}.`;this.logger.warn(i)}onTransportError(e){this.user.onTransportError&&this.user.onTransportError(e),this.stateTransition(g.Terminated,!0)}typeToString(){return"INVITE client transaction"}ack(e){const t=this.request.ruri,i=this.request.callId,s=this.request.cseq,r=this.request.getHeader("from"),n=e.getHeader("to"),a=this.request.getHeader("via"),d=this.request.getHeader("route");if(!r)throw new Error("From undefined.");if(!n)throw new Error("To undefined.");if(!a)throw new Error("Via undefined.");let f=`ACK ${t} SIP/2.0\r
|
|
39
|
-
`;d&&(
|
|
40
|
-
`),
|
|
41
|
-
`,
|
|
42
|
-
`,
|
|
43
|
-
`,
|
|
44
|
-
`,
|
|
45
|
-
`,
|
|
46
|
-
`,
|
|
38
|
+
`,{message:s}}class je extends he{constructor(e){super(e||"Unspecified transport error.")}}class ht{constructor(e,t,i,s,r){this._transport=e,this._user=t,this._id=i,this._state=s,this.listeners=new Array,this.logger=t.loggerFactory.getLogger(r,i),this.logger.debug(`Constructing ${this.typeToString()} with id ${this.id}.`)}dispose(){this.logger.debug(`Destroyed ${this.typeToString()} with id ${this.id}.`)}get id(){return this._id}get kind(){throw new Error("Invalid kind.")}get state(){return this._state}get transport(){return this._transport}addStateChangeListener(e,t){const i=()=>{this.removeStateChangeListener(i),e()};t?.once===!0?this.listeners.push(i):this.listeners.push(e)}notifyStateChangeListeners(){this.listeners.slice().forEach(e=>e())}removeStateChangeListener(e){this.listeners=this.listeners.filter(t=>t!==e)}logTransportError(e,t){this.logger.error(e.message),this.logger.error(`Transport error occurred in ${this.typeToString()} with id ${this.id}.`),this.logger.error(t)}send(e){return this.transport.send(e).catch(t=>{if(t instanceof je)throw this.onTransportError(t),t;let i;throw t&&typeof t.message=="string"?i=new je(t.message):i=new je,this.onTransportError(i),i})}setState(e){this.logger.debug(`State change to "${e}" on ${this.typeToString()} with id ${this.id}.`),this._state=e,this._user.onStateChange&&this._user.onStateChange(e),this.notifyStateChangeListeners()}typeToString(){return"UnknownType"}}class ut extends ht{constructor(e,t,i,s,r){super(t,i,e.viaBranch,s,r),this._request=e,this.user=i}get request(){return this._request}}var f;(function(a){a.Accepted="Accepted",a.Calling="Calling",a.Completed="Completed",a.Confirmed="Confirmed",a.Proceeding="Proceeding",a.Terminated="Terminated",a.Trying="Trying"})(f=f||(f={}));class U extends ut{constructor(e,t,i){super(e,t,i,f.Proceeding,"sip.transaction.ist")}dispose(){this.stopProgressExtensionTimer(),this.H&&(clearTimeout(this.H),this.H=void 0),this.I&&(clearTimeout(this.I),this.I=void 0),this.L&&(clearTimeout(this.L),this.L=void 0),super.dispose()}get kind(){return"ist"}receiveRequest(e){switch(this.state){case f.Proceeding:if(e.method===v.INVITE){this.lastProvisionalResponse&&this.send(this.lastProvisionalResponse).catch(i=>{this.logTransportError(i,"Failed to send retransmission of provisional response.")});return}break;case f.Accepted:if(e.method===v.INVITE)return;break;case f.Completed:if(e.method===v.INVITE){if(!this.lastFinalResponse)throw new Error("Last final response undefined.");this.send(this.lastFinalResponse).catch(i=>{this.logTransportError(i,"Failed to send retransmission of final response.")});return}if(e.method===v.ACK){this.stateTransition(f.Confirmed);return}break;case f.Confirmed:if(e.method===v.INVITE||e.method===v.ACK)return;break;case f.Terminated:if(e.method===v.INVITE||e.method===v.ACK)return;break;default:throw new Error(`Invalid state ${this.state}`)}const t=`INVITE server transaction received unexpected ${e.method} request while in state ${this.state}.`;this.logger.warn(t)}receiveResponse(e,t){if(e<100||e>699)throw new Error(`Invalid status code ${e}`);switch(this.state){case f.Proceeding:if(e>=100&&e<=199){this.lastProvisionalResponse=t,e>100&&this.startProgressExtensionTimer(),this.send(t).catch(s=>{this.logTransportError(s,"Failed to send 1xx response.")});return}if(e>=200&&e<=299){this.lastFinalResponse=t,this.stateTransition(f.Accepted),this.send(t).catch(s=>{this.logTransportError(s,"Failed to send 2xx response.")});return}if(e>=300&&e<=699){this.lastFinalResponse=t,this.stateTransition(f.Completed),this.send(t).catch(s=>{this.logTransportError(s,"Failed to send non-2xx final response.")});return}break;case f.Accepted:if(e>=200&&e<=299){this.send(t).catch(s=>{this.logTransportError(s,"Failed to send 2xx response.")});return}break;case f.Completed:break;case f.Confirmed:break;case f.Terminated:break;default:throw new Error(`Invalid state ${this.state}`)}const i=`INVITE server transaction received unexpected ${e} response from TU while in state ${this.state}.`;throw this.logger.error(i),new Error(i)}retransmitAcceptedResponse(){this.state===f.Accepted&&this.lastFinalResponse&&this.send(this.lastFinalResponse).catch(e=>{this.logTransportError(e,"Failed to send 2xx response.")})}onTransportError(e){this.user.onTransportError&&this.user.onTransportError(e)}typeToString(){return"INVITE server transaction"}stateTransition(e){const t=()=>{throw new Error(`Invalid state transition from ${this.state} to ${e}`)};switch(e){case f.Proceeding:t();break;case f.Accepted:case f.Completed:this.state!==f.Proceeding&&t();break;case f.Confirmed:this.state!==f.Completed&&t();break;case f.Terminated:this.state!==f.Accepted&&this.state!==f.Completed&&this.state!==f.Confirmed&&t();break;default:t()}this.stopProgressExtensionTimer(),e===f.Accepted&&(this.L=setTimeout(()=>this.timerL(),M.TIMER_L)),e===f.Completed&&(this.H=setTimeout(()=>this.timerH(),M.TIMER_H)),e===f.Confirmed&&(this.I=setTimeout(()=>this.timerI(),M.TIMER_I)),e===f.Terminated&&this.dispose(),this.setState(e)}startProgressExtensionTimer(){this.progressExtensionTimer===void 0&&(this.progressExtensionTimer=setInterval(()=>{if(this.logger.debug(`Progress extension timer expired for INVITE server transaction ${this.id}.`),!this.lastProvisionalResponse)throw new Error("Last provisional response undefined.");this.send(this.lastProvisionalResponse).catch(e=>{this.logTransportError(e,"Failed to send retransmission of provisional response.")})},M.PROVISIONAL_RESPONSE_INTERVAL))}stopProgressExtensionTimer(){this.progressExtensionTimer!==void 0&&(clearInterval(this.progressExtensionTimer),this.progressExtensionTimer=void 0)}timerG(){}timerH(){this.logger.debug(`Timer H expired for INVITE server transaction ${this.id}.`),this.state===f.Completed&&(this.logger.warn("ACK to negative final response was never received, terminating transaction."),this.stateTransition(f.Terminated))}timerI(){this.logger.debug(`Timer I expired for INVITE server transaction ${this.id}.`),this.stateTransition(f.Terminated)}timerL(){this.logger.debug(`Timer L expired for INVITE server transaction ${this.id}.`),this.state===f.Accepted&&this.stateTransition(f.Terminated)}}class He extends ht{constructor(e,t,i,s,r){super(t,i,He.makeId(e),s,r),this._request=e,this.user=i,e.setViaHeader(this.id,t.protocol)}static makeId(e){if(e.method==="CANCEL"){if(!e.branch)throw new Error("Outgoing CANCEL request without a branch.");return e.branch}else return"z9hG4bK"+Math.floor(Math.random()*1e7)}get request(){return this._request}onRequestTimeout(){this.user.onRequestTimeout&&this.user.onRequestTimeout()}}class B extends He{constructor(e,t,i){super(e,t,i,f.Trying,"sip.transaction.nict"),this.F=setTimeout(()=>this.timerF(),M.TIMER_F),this.send(e.toString()).catch(s=>{this.logTransportError(s,"Failed to send initial outgoing request.")})}dispose(){this.F&&(clearTimeout(this.F),this.F=void 0),this.K&&(clearTimeout(this.K),this.K=void 0),super.dispose()}get kind(){return"nict"}receiveResponse(e){const t=e.statusCode;if(!t||t<100||t>699)throw new Error(`Invalid status code ${t}`);switch(this.state){case f.Trying:if(t>=100&&t<=199){this.stateTransition(f.Proceeding),this.user.receiveResponse&&this.user.receiveResponse(e);return}if(t>=200&&t<=699){if(this.stateTransition(f.Completed),t===408){this.onRequestTimeout();return}this.user.receiveResponse&&this.user.receiveResponse(e);return}break;case f.Proceeding:if(t>=100&&t<=199&&this.user.receiveResponse)return this.user.receiveResponse(e);if(t>=200&&t<=699){if(this.stateTransition(f.Completed),t===408){this.onRequestTimeout();return}this.user.receiveResponse&&this.user.receiveResponse(e);return}break;case f.Completed:return;case f.Terminated:return;default:throw new Error(`Invalid state ${this.state}`)}const i=`Non-INVITE client transaction received unexpected ${t} response while in state ${this.state}.`;this.logger.warn(i)}onTransportError(e){this.user.onTransportError&&this.user.onTransportError(e),this.stateTransition(f.Terminated,!0)}typeToString(){return"non-INVITE client transaction"}stateTransition(e,t=!1){const i=()=>{throw new Error(`Invalid state transition from ${this.state} to ${e}`)};switch(e){case f.Trying:i();break;case f.Proceeding:this.state!==f.Trying&&i();break;case f.Completed:this.state!==f.Trying&&this.state!==f.Proceeding&&i();break;case f.Terminated:this.state!==f.Trying&&this.state!==f.Proceeding&&this.state!==f.Completed&&(t||i());break;default:i()}e===f.Completed&&(this.F&&(clearTimeout(this.F),this.F=void 0),this.K=setTimeout(()=>this.timerK(),M.TIMER_K)),e===f.Terminated&&this.dispose(),this.setState(e)}timerF(){this.logger.debug(`Timer F expired for non-INVITE client transaction ${this.id}.`),(this.state===f.Trying||this.state===f.Proceeding)&&(this.onRequestTimeout(),this.stateTransition(f.Terminated))}timerK(){this.state===f.Completed&&this.stateTransition(f.Terminated)}}class be{constructor(e,t){this.core=e,this.dialogState=t,this.core.dialogs.set(this.id,this)}static initialDialogStateForUserAgentClient(e,t){const s=t.getHeaders("record-route").reverse(),r=t.parseHeader("contact");if(!r)throw new Error("Contact undefined.");if(!(r instanceof N))throw new Error("Contact not instance of NameAddrHeader.");const n=r.uri,o=e.cseq,d=void 0,u=e.callId,h=e.fromTag,m=t.toTag;if(!u)throw new Error("Call id undefined.");if(!h)throw new Error("From tag undefined.");if(!m)throw new Error("To tag undefined.");if(!e.from)throw new Error("From undefined.");if(!e.to)throw new Error("To undefined.");const S=e.from.uri,x=e.to.uri;if(!t.statusCode)throw new Error("Incoming response status code undefined.");const _=t.statusCode<200;return{id:u+h+m,early:_,callId:u,localTag:h,remoteTag:m,localSequenceNumber:o,remoteSequenceNumber:d,localURI:S,remoteURI:x,remoteTarget:n,routeSet:s,secure:!1}}static initialDialogStateForUserAgentServer(e,t,i=!1){const r=e.getHeaders("record-route"),n=e.parseHeader("contact");if(!n)throw new Error("Contact undefined.");if(!(n instanceof N))throw new Error("Contact not instance of NameAddrHeader.");const o=n.uri,d=e.cseq,u=void 0,h=e.callId,m=t,S=e.fromTag,x=e.from.uri,_=e.to.uri;return{id:h+m+S,early:i,callId:h,localTag:m,remoteTag:S,localSequenceNumber:u,remoteSequenceNumber:d,localURI:_,remoteURI:x,remoteTarget:o,routeSet:r,secure:!1}}dispose(){this.core.dialogs.delete(this.id)}get id(){return this.dialogState.id}get early(){return this.dialogState.early}get callId(){return this.dialogState.callId}get localTag(){return this.dialogState.localTag}get remoteTag(){return this.dialogState.remoteTag}get localSequenceNumber(){return this.dialogState.localSequenceNumber}get remoteSequenceNumber(){return this.dialogState.remoteSequenceNumber}get localURI(){return this.dialogState.localURI}get remoteURI(){return this.dialogState.remoteURI}get remoteTarget(){return this.dialogState.remoteTarget}get routeSet(){return this.dialogState.routeSet}get secure(){return this.dialogState.secure}get userAgentCore(){return this.core}confirm(){this.dialogState.early=!1}receiveRequest(e){if(e.method!==v.ACK){if(this.remoteSequenceNumber){if(e.cseq<=this.remoteSequenceNumber)throw new Error("Out of sequence in dialog request. Did you forget to call sequenceGuard()?");this.dialogState.remoteSequenceNumber=e.cseq}this.remoteSequenceNumber||(this.dialogState.remoteSequenceNumber=e.cseq)}}recomputeRouteSet(e){this.dialogState.routeSet=e.getHeaders("record-route").reverse()}createOutgoingRequestMessage(e,t){const i=this.remoteURI,s=this.remoteTag,r=this.localURI,n=this.localTag,o=this.callId;let d;t&&t.cseq?d=t.cseq:this.dialogState.localSequenceNumber?d=this.dialogState.localSequenceNumber+=1:d=this.dialogState.localSequenceNumber=1;const u=this.remoteTarget,h=this.routeSet,m=t&&t.extraHeaders,S=t&&t.body;return this.userAgentCore.makeOutgoingRequestMessage(e,u,r,i,{callId:o,cseq:d,fromTag:n,toTag:s,routeSet:h},m,S)}incrementLocalSequenceNumber(){if(!this.dialogState.localSequenceNumber)throw new Error("Local sequence number undefined.");this.dialogState.localSequenceNumber+=1}sequenceGuard(e){return e.method===v.ACK?!0:this.remoteSequenceNumber&&e.cseq<=this.remoteSequenceNumber?(this.core.replyStateless(e,{statusCode:500}),!1):!0}}class ce extends He{constructor(e,t,i){super(e,t,i,f.Calling,"sip.transaction.ict"),this.ackRetransmissionCache=new Map,this.B=setTimeout(()=>this.timerB(),M.TIMER_B),this.send(e.toString()).catch(s=>{this.logTransportError(s,"Failed to send initial outgoing request.")})}dispose(){this.B&&(clearTimeout(this.B),this.B=void 0),this.D&&(clearTimeout(this.D),this.D=void 0),this.M&&(clearTimeout(this.M),this.M=void 0),super.dispose()}get kind(){return"ict"}ackResponse(e){const t=e.toTag;if(!t)throw new Error("To tag undefined.");const i="z9hG4bK"+Math.floor(Math.random()*1e7);e.setViaHeader(i,this.transport.protocol),this.ackRetransmissionCache.set(t,e),this.send(e.toString()).catch(s=>{this.logTransportError(s,"Failed to send ACK to 2xx response.")})}receiveResponse(e){const t=e.statusCode;if(!t||t<100||t>699)throw new Error(`Invalid status code ${t}`);switch(this.state){case f.Calling:if(t>=100&&t<=199){this.stateTransition(f.Proceeding),this.user.receiveResponse&&this.user.receiveResponse(e);return}if(t>=200&&t<=299){this.ackRetransmissionCache.set(e.toTag,void 0),this.stateTransition(f.Accepted),this.user.receiveResponse&&this.user.receiveResponse(e);return}if(t>=300&&t<=699){this.stateTransition(f.Completed),this.ack(e),this.user.receiveResponse&&this.user.receiveResponse(e);return}break;case f.Proceeding:if(t>=100&&t<=199){this.user.receiveResponse&&this.user.receiveResponse(e);return}if(t>=200&&t<=299){this.ackRetransmissionCache.set(e.toTag,void 0),this.stateTransition(f.Accepted),this.user.receiveResponse&&this.user.receiveResponse(e);return}if(t>=300&&t<=699){this.stateTransition(f.Completed),this.ack(e),this.user.receiveResponse&&this.user.receiveResponse(e);return}break;case f.Accepted:if(t>=200&&t<=299){if(!this.ackRetransmissionCache.has(e.toTag)){this.ackRetransmissionCache.set(e.toTag,void 0),this.user.receiveResponse&&this.user.receiveResponse(e);return}const s=this.ackRetransmissionCache.get(e.toTag);if(s){this.send(s.toString()).catch(r=>{this.logTransportError(r,"Failed to send retransmission of ACK to 2xx response.")});return}return}break;case f.Completed:if(t>=300&&t<=699){this.ack(e);return}break;case f.Terminated:break;default:throw new Error(`Invalid state ${this.state}`)}const i=`Received unexpected ${t} response while in state ${this.state}.`;this.logger.warn(i)}onTransportError(e){this.user.onTransportError&&this.user.onTransportError(e),this.stateTransition(f.Terminated,!0)}typeToString(){return"INVITE client transaction"}ack(e){const t=this.request.ruri,i=this.request.callId,s=this.request.cseq,r=this.request.getHeader("from"),n=e.getHeader("to"),o=this.request.getHeader("via"),d=this.request.getHeader("route");if(!r)throw new Error("From undefined.");if(!n)throw new Error("To undefined.");if(!o)throw new Error("Via undefined.");let u=`ACK ${t} SIP/2.0\r
|
|
39
|
+
`;d&&(u+=`Route: ${d}\r
|
|
40
|
+
`),u+=`Via: ${o}\r
|
|
41
|
+
`,u+=`To: ${n}\r
|
|
42
|
+
`,u+=`From: ${r}\r
|
|
43
|
+
`,u+=`Call-ID: ${i}\r
|
|
44
|
+
`,u+=`CSeq: ${s} ACK\r
|
|
45
|
+
`,u+=`Max-Forwards: 70\r
|
|
46
|
+
`,u+=`Content-Length: 0\r
|
|
47
47
|
\r
|
|
48
|
-
`,this.send(f).catch(h=>{this.logTransportError(h,"Failed to send ACK to non-2xx response.")})}stateTransition(e,t=!1){const i=()=>{throw new Error(`Invalid state transition from ${this.state} to ${e}`)};switch(e){case g.Calling:i();break;case g.Proceeding:this.state!==g.Calling&&i();break;case g.Accepted:case g.Completed:this.state!==g.Calling&&this.state!==g.Proceeding&&i();break;case g.Terminated:this.state!==g.Calling&&this.state!==g.Accepted&&this.state!==g.Completed&&(t||i());break;default:i()}this.B&&(clearTimeout(this.B),this.B=void 0),g.Proceeding,e===g.Completed&&(this.D=setTimeout(()=>this.timerD(),M.TIMER_D)),e===g.Accepted&&(this.M=setTimeout(()=>this.timerM(),M.TIMER_M)),e===g.Terminated&&this.dispose(),this.setState(e)}timerA(){}timerB(){this.logger.debug(`Timer B expired for INVITE client transaction ${this.id}.`),this.state===g.Calling&&(this.onRequestTimeout(),this.stateTransition(g.Terminated))}timerD(){this.logger.debug(`Timer D expired for INVITE client transaction ${this.id}.`),this.state===g.Completed&&this.stateTransition(g.Terminated)}timerM(){this.logger.debug(`Timer M expired for INVITE client transaction ${this.id}.`),this.state===g.Accepted&&this.stateTransition(g.Terminated)}}class O{constructor(e,t,i,s){this.transactionConstructor=e,this.core=t,this.message=i,this.delegate=s,this.challenged=!1,this.stale=!1,this.logger=this.loggerFactory.getLogger("sip.user-agent-client"),this.init()}dispose(){this.transaction.dispose()}get loggerFactory(){return this.core.loggerFactory}get transaction(){if(!this._transaction)throw new Error("Transaction undefined.");return this._transaction}cancel(e,t={}){if(!this.transaction)throw new Error("Transaction undefined.");if(!this.message.to)throw new Error("To undefined.");if(!this.message.from)throw new Error("From undefined.");const i=this.core.makeOutgoingRequestMessage(v.CANCEL,this.message.ruri,this.message.from.uri,this.message.to.uri,{toTag:this.message.toTag,fromTag:this.message.fromTag,callId:this.message.callId,cseq:this.message.cseq},t.extraHeaders);return i.branch=this.message.branch,this.message.headers.Route&&(i.headers.Route=this.message.headers.Route),e&&i.setHeader("Reason",e),this.transaction.state===g.Proceeding?new O(B,this.core,i):this.transaction.addStateChangeListener(()=>{this.transaction&&this.transaction.state===g.Proceeding&&new O(B,this.core,i)},{once:!0}),i}authenticationGuard(e,t){const i=e.statusCode;if(!i)throw new Error("Response status code undefined.");if(i!==401&&i!==407)return!0;let s,r;if(i===401?(s=e.parseHeader("www-authenticate"),r="authorization"):(s=e.parseHeader("proxy-authenticate"),r="proxy-authorization"),!s)return this.logger.warn(i+" with wrong or missing challenge, cannot authenticate"),!0;if(this.challenged&&(this.stale||s.stale!==!0))return this.logger.warn(i+" apparently in authentication loop, cannot authenticate"),!0;if(!this.credentials&&(this.credentials=this.core.configuration.authenticationFactory(),!this.credentials))return this.logger.warn("Unable to obtain credentials, cannot authenticate"),!0;if(!this.credentials.authenticate(this.message,s))return!0;this.challenged=!0,s.stale&&(this.stale=!0);let n=this.message.cseq+=1;return t&&t.localSequenceNumber&&(t.incrementLocalSequenceNumber(),n=this.message.cseq=t.localSequenceNumber),this.message.setHeader("cseq",n+" "+this.message.method),this.message.setHeader(r,this.credentials.toString()),this.init(),!1}onRequestTimeout(){this.logger.warn("User agent client request timed out. Generating internal 408 Request Timeout.");const e=new se;e.statusCode=408,e.reasonPhrase="Request Timeout",this.receiveResponse(e)}onTransportError(e){this.logger.error(e.message),this.logger.error("User agent client request transport error. Generating internal 503 Service Unavailable.");const t=new se;t.statusCode=503,t.reasonPhrase="Service Unavailable",this.receiveResponse(t)}receiveResponse(e){if(!this.authenticationGuard(e))return;const t=e.statusCode?e.statusCode.toString():"";if(!t)throw new Error("Response status code undefined.");switch(!0){case/^100$/.test(t):this.delegate&&this.delegate.onTrying&&this.delegate.onTrying({message:e});break;case/^1[0-9]{2}$/.test(t):this.delegate&&this.delegate.onProgress&&this.delegate.onProgress({message:e});break;case/^2[0-9]{2}$/.test(t):this.delegate&&this.delegate.onAccept&&this.delegate.onAccept({message:e});break;case/^3[0-9]{2}$/.test(t):this.delegate&&this.delegate.onRedirect&&this.delegate.onRedirect({message:e});break;case/^[4-6][0-9]{2}$/.test(t):this.delegate&&this.delegate.onReject&&this.delegate.onReject({message:e});break;default:throw new Error(`Invalid status code ${t}`)}}init(){const e={loggerFactory:this.loggerFactory,onRequestTimeout:()=>this.onRequestTimeout(),onStateChange:s=>{s===g.Terminated&&(this.core.userAgentClients.delete(i),t===this._transaction&&this.dispose())},onTransportError:s=>this.onTransportError(s),receiveResponse:s=>this.receiveResponse(s)},t=new this.transactionConstructor(this.message,this.core.transport,e);this._transaction=t;const i=t.id+t.request.method;this.core.userAgentClients.set(i,this)}}class Wt extends O{constructor(e,t,i){const s=e.createOutgoingRequestMessage(v.BYE,i);super(B,e.userAgentCore,s,t),e.dispose()}}class j extends ht{constructor(e,t,i){super(e,t,i,g.Trying,"sip.transaction.nist")}dispose(){this.J&&(clearTimeout(this.J),this.J=void 0),super.dispose()}get kind(){return"nist"}receiveRequest(e){switch(this.state){case g.Trying:break;case g.Proceeding:if(!this.lastResponse)throw new Error("Last response undefined.");this.send(this.lastResponse).catch(t=>{this.logTransportError(t,"Failed to send retransmission of provisional response.")});break;case g.Completed:if(!this.lastResponse)throw new Error("Last response undefined.");this.send(this.lastResponse).catch(t=>{this.logTransportError(t,"Failed to send retransmission of final response.")});break;case g.Terminated:break;default:throw new Error(`Invalid state ${this.state}`)}}receiveResponse(e,t){if(e<100||e>699)throw new Error(`Invalid status code ${e}`);if(e>100&&e<=199)throw new Error("Provisional response other than 100 not allowed.");switch(this.state){case g.Trying:if(this.lastResponse=t,e>=100&&e<200){this.stateTransition(g.Proceeding),this.send(t).catch(s=>{this.logTransportError(s,"Failed to send provisional response.")});return}if(e>=200&&e<=699){this.stateTransition(g.Completed),this.send(t).catch(s=>{this.logTransportError(s,"Failed to send final response.")});return}break;case g.Proceeding:if(this.lastResponse=t,e>=200&&e<=699){this.stateTransition(g.Completed),this.send(t).catch(s=>{this.logTransportError(s,"Failed to send final response.")});return}break;case g.Completed:return;case g.Terminated:break;default:throw new Error(`Invalid state ${this.state}`)}const i=`Non-INVITE server transaction received unexpected ${e} response from TU while in state ${this.state}.`;throw this.logger.error(i),new Error(i)}onTransportError(e){this.user.onTransportError&&this.user.onTransportError(e),this.stateTransition(g.Terminated,!0)}typeToString(){return"non-INVITE server transaction"}stateTransition(e,t=!1){const i=()=>{throw new Error(`Invalid state transition from ${this.state} to ${e}`)};switch(e){case g.Trying:i();break;case g.Proceeding:this.state!==g.Trying&&i();break;case g.Completed:this.state!==g.Trying&&this.state!==g.Proceeding&&i();break;case g.Terminated:this.state!==g.Proceeding&&this.state!==g.Completed&&(t||i());break;default:i()}e===g.Completed&&(this.J=setTimeout(()=>this.timerJ(),M.TIMER_J)),e===g.Terminated&&this.dispose(),this.setState(e)}timerJ(){this.logger.debug(`Timer J expired for NON-INVITE server transaction ${this.id}.`),this.state===g.Completed&&this.stateTransition(g.Terminated)}}class Z{constructor(e,t,i,s){this.transactionConstructor=e,this.core=t,this.message=i,this.delegate=s,this.logger=this.loggerFactory.getLogger("sip.user-agent-server"),this.toTag=i.toTag?i.toTag:Ae(),this.init()}dispose(){this.transaction.dispose()}get loggerFactory(){return this.core.loggerFactory}get transaction(){if(!this._transaction)throw new Error("Transaction undefined.");return this._transaction}accept(e={statusCode:200}){if(!this.acceptable)throw new re(`${this.message.method} not acceptable in state ${this.transaction.state}.`);const t=e.statusCode;if(t<200||t>299)throw new TypeError(`Invalid statusCode: ${t}`);return this.reply(e)}progress(e={statusCode:180}){if(!this.progressable)throw new re(`${this.message.method} not progressable in state ${this.transaction.state}.`);const t=e.statusCode;if(t<101||t>199)throw new TypeError(`Invalid statusCode: ${t}`);return this.reply(e)}redirect(e,t={statusCode:302}){if(!this.redirectable)throw new re(`${this.message.method} not redirectable in state ${this.transaction.state}.`);const i=t.statusCode;if(i<300||i>399)throw new TypeError(`Invalid statusCode: ${i}`);const s=new Array;return e.forEach(n=>s.push(`Contact: ${n.toString()}`)),t.extraHeaders=(t.extraHeaders||[]).concat(s),this.reply(t)}reject(e={statusCode:480}){if(!this.rejectable)throw new re(`${this.message.method} not rejectable in state ${this.transaction.state}.`);const t=e.statusCode;if(t<400||t>699)throw new TypeError(`Invalid statusCode: ${t}`);return this.reply(e)}trying(e){if(!this.tryingable)throw new re(`${this.message.method} not tryingable in state ${this.transaction.state}.`);return this.reply({statusCode:100})}receiveCancel(e){this.delegate&&this.delegate.onCancel&&this.delegate.onCancel(e)}get acceptable(){if(this.transaction instanceof U)return this.transaction.state===g.Proceeding||this.transaction.state===g.Accepted;if(this.transaction instanceof j)return this.transaction.state===g.Trying||this.transaction.state===g.Proceeding;throw new Error("Unknown transaction type.")}get progressable(){if(this.transaction instanceof U)return this.transaction.state===g.Proceeding;if(this.transaction instanceof j)return!1;throw new Error("Unknown transaction type.")}get redirectable(){if(this.transaction instanceof U)return this.transaction.state===g.Proceeding;if(this.transaction instanceof j)return this.transaction.state===g.Trying||this.transaction.state===g.Proceeding;throw new Error("Unknown transaction type.")}get rejectable(){if(this.transaction instanceof U)return this.transaction.state===g.Proceeding;if(this.transaction instanceof j)return this.transaction.state===g.Trying||this.transaction.state===g.Proceeding;throw new Error("Unknown transaction type.")}get tryingable(){if(this.transaction instanceof U)return this.transaction.state===g.Proceeding;if(this.transaction instanceof j)return this.transaction.state===g.Trying;throw new Error("Unknown transaction type.")}reply(e){!e.toTag&&e.statusCode!==100&&(e.toTag=this.toTag),e.userAgent=e.userAgent||this.core.configuration.userAgentHeaderFieldValue,e.supported=e.supported||this.core.configuration.supportedOptionTagsResponse;const t=dt(this.message,e);return this.transaction.receiveResponse(e.statusCode,t.message),t}init(){const e={loggerFactory:this.loggerFactory,onStateChange:s=>{s===g.Terminated&&(this.core.userAgentServers.delete(i),this.dispose())},onTransportError:s=>{this.logger.error(s.message),this.delegate&&this.delegate.onTransportError?this.delegate.onTransportError(s):this.logger.error("User agent server response transport error.")}},t=new this.transactionConstructor(this.message,this.core.transport,e);this._transaction=t;const i=t.id;this.core.userAgentServers.set(t.id,this)}}class Kt extends Z{constructor(e,t,i){super(j,e.userAgentCore,t,i)}}class zt extends O{constructor(e,t,i){const s=e.createOutgoingRequestMessage(v.INFO,i);super(B,e.userAgentCore,s,t)}}class Yt extends Z{constructor(e,t,i){super(j,e.userAgentCore,t,i)}}class ut extends O{constructor(e,t,i){super(B,e,t,i)}}class gt extends Z{constructor(e,t,i){super(j,e,t,i)}}class Jt extends O{constructor(e,t,i){const s=e.createOutgoingRequestMessage(v.NOTIFY,i);super(B,e.userAgentCore,s,t)}}function Zt(o){return o.userAgentCore!==void 0}class He extends Z{constructor(e,t,i){const s=Zt(e)?e.userAgentCore:e;super(j,s,t,i)}}class Xt extends O{constructor(e,t,i){const s=e.createOutgoingRequestMessage(v.PRACK,i);super(B,e.userAgentCore,s,t),e.signalingStateTransition(s)}}class Qt extends Z{constructor(e,t,i){super(j,e.userAgentCore,t,i),e.signalingStateTransition(t),this.dialog=e}accept(e={statusCode:200}){return e.body&&this.dialog.signalingStateTransition(e.body),super.accept(e)}}class ei extends O{constructor(e,t,i){const s=e.createOutgoingRequestMessage(v.INVITE,i);super(ae,e.userAgentCore,s,t),this.delegate=t,e.signalingStateTransition(s),e.reinviteUserAgentClient=this,this.dialog=e}receiveResponse(e){if(!this.authenticationGuard(e,this.dialog))return;const t=e.statusCode?e.statusCode.toString():"";if(!t)throw new Error("Response status code undefined.");switch(!0){case/^100$/.test(t):this.delegate&&this.delegate.onTrying&&this.delegate.onTrying({message:e});break;case/^1[0-9]{2}$/.test(t):this.delegate&&this.delegate.onProgress&&this.delegate.onProgress({message:e,session:this.dialog,prack:i=>{throw new Error("Unimplemented.")}});break;case/^2[0-9]{2}$/.test(t):this.dialog.signalingStateTransition(e),this.delegate&&this.delegate.onAccept&&this.delegate.onAccept({message:e,session:this.dialog,ack:i=>this.dialog.ack(i)});break;case/^3[0-9]{2}$/.test(t):this.dialog.signalingStateRollback(),this.dialog.reinviteUserAgentClient=void 0,this.delegate&&this.delegate.onRedirect&&this.delegate.onRedirect({message:e});break;case/^[4-6][0-9]{2}$/.test(t):this.dialog.signalingStateRollback(),this.dialog.reinviteUserAgentClient=void 0,this.delegate&&this.delegate.onReject&&this.delegate.onReject({message:e});break;default:throw new Error(`Invalid status code ${t}`)}}}class ti extends Z{constructor(e,t,i){super(U,e.userAgentCore,t,i),e.reinviteUserAgentServer=this,this.dialog=e}accept(e={statusCode:200}){e.extraHeaders=e.extraHeaders||[],e.extraHeaders=e.extraHeaders.concat(this.dialog.routeSet.map(r=>`Record-Route: ${r}`));const t=super.accept(e),i=this.dialog,s=Object.assign(Object.assign({},t),{session:i});return e.body&&this.dialog.signalingStateTransition(e.body),this.dialog.reConfirm(),s}progress(e={statusCode:180}){const t=super.progress(e),i=this.dialog,s=Object.assign(Object.assign({},t),{session:i});return e.body&&this.dialog.signalingStateTransition(e.body),s}redirect(e,t={statusCode:302}){throw this.dialog.signalingStateRollback(),this.dialog.reinviteUserAgentServer=void 0,new Error("Unimplemented.")}reject(e={statusCode:488}){return this.dialog.signalingStateRollback(),this.dialog.reinviteUserAgentServer=void 0,super.reject(e)}}class ii extends O{constructor(e,t,i){const s=e.createOutgoingRequestMessage(v.REFER,i);super(B,e.userAgentCore,s,t)}}function si(o){return o.userAgentCore!==void 0}class ft extends Z{constructor(e,t,i){const s=si(e)?e.userAgentCore:e;super(j,s,t,i)}}class Me extends we{constructor(e,t,i,s){super(t,i),this.initialTransaction=e,this._signalingState=b.Initial,this.ackWait=!1,this.ackProcessing=!1,this.delegate=s,e instanceof U&&(this.ackWait=!0),this.early||this.start2xxRetransmissionTimer(),this.signalingStateTransition(e.request),this.logger=t.loggerFactory.getLogger("sip.invite-dialog"),this.logger.log(`INVITE dialog ${this.id} constructed`)}dispose(){super.dispose(),this._signalingState=b.Closed,this._offer=void 0,this._answer=void 0,this.invite2xxTimer&&(clearTimeout(this.invite2xxTimer),this.invite2xxTimer=void 0),this.logger.log(`INVITE dialog ${this.id} destroyed`)}get sessionState(){return this.early?V.Early:this.ackWait?V.AckWait:this._signalingState===b.Closed?V.Terminated:V.Confirmed}get signalingState(){return this._signalingState}get offer(){return this._offer}get answer(){return this._answer}confirm(){this.early&&this.start2xxRetransmissionTimer(),super.confirm()}reConfirm(){this.reinviteUserAgentServer&&this.startReInvite2xxRetransmissionTimer()}ack(e={}){this.logger.log(`INVITE dialog ${this.id} sending ACK request`);let t;if(this.reinviteUserAgentClient){if(!(this.reinviteUserAgentClient.transaction instanceof ae))throw new Error("Transaction not instance of InviteClientTransaction.");t=this.reinviteUserAgentClient.transaction,this.reinviteUserAgentClient=void 0}else{if(!(this.initialTransaction instanceof ae))throw new Error("Initial transaction not instance of InviteClientTransaction.");t=this.initialTransaction}const i=this.createOutgoingRequestMessage(v.ACK,{cseq:t.request.cseq,extraHeaders:e.extraHeaders,body:e.body});return t.ackResponse(i),this.signalingStateTransition(i),{message:i}}bye(e,t){if(this.logger.log(`INVITE dialog ${this.id} sending BYE request`),this.initialTransaction instanceof U){if(this.early)throw new Error("UAS MUST NOT send a BYE on early dialogs.");if(this.ackWait&&this.initialTransaction.state!==g.Terminated)throw new Error("UAS MUST NOT send a BYE on a confirmed dialog until it has received an ACK for its 2xx response or until the server transaction times out.")}return new Wt(this,e,t)}info(e,t){if(this.logger.log(`INVITE dialog ${this.id} sending INFO request`),this.early)throw new Error("Dialog not confirmed.");return new zt(this,e,t)}invite(e,t){if(this.logger.log(`INVITE dialog ${this.id} sending INVITE request`),this.early)throw new Error("Dialog not confirmed.");if(this.reinviteUserAgentClient)throw new Error("There is an ongoing re-INVITE client transaction.");if(this.reinviteUserAgentServer)throw new Error("There is an ongoing re-INVITE server transaction.");return new ei(this,e,t)}message(e,t){if(this.logger.log(`INVITE dialog ${this.id} sending MESSAGE request`),this.early)throw new Error("Dialog not confirmed.");const i=this.createOutgoingRequestMessage(v.MESSAGE,t);return new ut(this.core,i,e)}notify(e,t){if(this.logger.log(`INVITE dialog ${this.id} sending NOTIFY request`),this.early)throw new Error("Dialog not confirmed.");return new Jt(this,e,t)}prack(e,t){return this.logger.log(`INVITE dialog ${this.id} sending PRACK request`),new Xt(this,e,t)}refer(e,t){if(this.logger.log(`INVITE dialog ${this.id} sending REFER request`),this.early)throw new Error("Dialog not confirmed.");return new ii(this,e,t)}receiveRequest(e){if(this.logger.log(`INVITE dialog ${this.id} received ${e.method} request`),e.method===v.ACK){if(this.ackWait){if(this.initialTransaction instanceof ae){this.logger.warn(`INVITE dialog ${this.id} received unexpected ${e.method} request, dropping.`);return}if(this.initialTransaction.request.cseq!==e.cseq){this.logger.warn(`INVITE dialog ${this.id} received unexpected ${e.method} request, dropping.`);return}this.ackWait=!1}else{if(!this.reinviteUserAgentServer){this.logger.warn(`INVITE dialog ${this.id} received unexpected ${e.method} request, dropping.`);return}if(this.reinviteUserAgentServer.transaction.request.cseq!==e.cseq){this.logger.warn(`INVITE dialog ${this.id} received unexpected ${e.method} request, dropping.`);return}this.reinviteUserAgentServer=void 0}if(this.signalingStateTransition(e),this.delegate&&this.delegate.onAck){const t=this.delegate.onAck({message:e});t instanceof Promise&&(this.ackProcessing=!0,t.then(()=>this.ackProcessing=!1).catch(()=>this.ackProcessing=!1))}return}if(!this.sequenceGuard(e)){this.logger.log(`INVITE dialog ${this.id} rejected out of order ${e.method} request.`);return}if(super.receiveRequest(e),e.method===v.INVITE){const t=()=>{const r=this.ackWait?"waiting for initial ACK":"processing initial ACK";this.logger.warn(`INVITE dialog ${this.id} received re-INVITE while ${r}`);let n="RFC 5407 suggests the following to avoid this race condition... ";n+=" Note: Implementation issues are outside the scope of this document,",n+=" but the following tip is provided for avoiding race conditions of",n+=" this type. The caller can delay sending re-INVITE F6 for some period",n+=" of time (2 seconds, perhaps), after which the caller can reasonably",n+=" assume that its ACK has been received. Implementors can decouple the",n+=" actions of the user (e.g., pressing the hold button) from the actions",n+=" of the protocol (the sending of re-INVITE F6), so that the UA can",n+=" behave like this. In this case, it is the implementor's choice as to",n+=" how long to wait. In most cases, such an implementation may be",n+=" useful to prevent the type of race condition shown in this section.",n+=" This document expresses no preference about whether or not they",n+=" should wait for an ACK to be delivered. After considering the impact",n+=" on user experience, implementors should decide whether or not to wait",n+=" for a while, because the user experience depends on the",n+=" implementation and has no direct bearing on protocol behavior.",this.logger.warn(n)},s=[`Retry-After: ${Math.floor(Math.random()*10)+1}`];if(this.ackProcessing){this.core.replyStateless(e,{statusCode:500,extraHeaders:s}),t();return}if(this.ackWait&&this.signalingState!==b.Stable){this.core.replyStateless(e,{statusCode:500,extraHeaders:s}),t();return}if(this.reinviteUserAgentServer){this.core.replyStateless(e,{statusCode:500,extraHeaders:s});return}if(this.reinviteUserAgentClient){this.core.replyStateless(e,{statusCode:491});return}}if(e.method===v.INVITE){const t=e.parseHeader("contact");if(!t)throw new Error("Contact undefined.");if(!(t instanceof N))throw new Error("Contact not instance of NameAddrHeader.");this.dialogState.remoteTarget=t.uri}switch(e.method){case v.BYE:{const t=new Kt(this,e);this.delegate&&this.delegate.onBye?this.delegate.onBye(t):t.accept(),this.dispose()}break;case v.INFO:{const t=new Yt(this,e);this.delegate&&this.delegate.onInfo?this.delegate.onInfo(t):t.reject({statusCode:469,extraHeaders:["Recv-Info:"]})}break;case v.INVITE:{const t=new ti(this,e);this.signalingStateTransition(e),this.delegate&&this.delegate.onInvite?this.delegate.onInvite(t):t.reject({statusCode:488})}break;case v.MESSAGE:{const t=new gt(this.core,e);this.delegate&&this.delegate.onMessage?this.delegate.onMessage(t):t.accept()}break;case v.NOTIFY:{const t=new He(this,e);this.delegate&&this.delegate.onNotify?this.delegate.onNotify(t):t.accept()}break;case v.PRACK:{const t=new Qt(this,e);this.delegate&&this.delegate.onPrack?this.delegate.onPrack(t):t.accept()}break;case v.REFER:{const t=new ft(this,e);this.delegate&&this.delegate.onRefer?this.delegate.onRefer(t):t.reject()}break;default:this.logger.log(`INVITE dialog ${this.id} received unimplemented ${e.method} request`),this.core.replyStateless(e,{statusCode:501});break}}reliableSequenceGuard(e){const t=e.statusCode;if(!t)throw new Error("Status code undefined");if(t>100&&t<200){const i=e.getHeader("require"),s=e.getHeader("rseq"),r=i&&i.includes("100rel")&&s?Number(s):void 0;if(r){if(this.rseq&&this.rseq+1!==r)return!1;this.rseq=this.rseq?this.rseq+1:r}}return!0}signalingStateRollback(){(this._signalingState===b.HaveLocalOffer||this.signalingState===b.HaveRemoteOffer)&&this._rollbackOffer&&this._rollbackAnswer&&(this._signalingState=b.Stable,this._offer=this._rollbackOffer,this._answer=this._rollbackAnswer)}signalingStateTransition(e){const t=Ce(e);if(!(!t||t.contentDisposition!=="session")){if(this._signalingState===b.Stable&&(this._rollbackOffer=this._offer,this._rollbackAnswer=this._answer),e instanceof pe)switch(this._signalingState){case b.Initial:case b.Stable:this._signalingState=b.HaveRemoteOffer,this._offer=t,this._answer=void 0;break;case b.HaveLocalOffer:this._signalingState=b.Stable,this._answer=t;break;case b.HaveRemoteOffer:break;case b.Closed:break;default:throw new Error("Unexpected signaling state.")}if(e instanceof se)switch(this._signalingState){case b.Initial:case b.Stable:this._signalingState=b.HaveRemoteOffer,this._offer=t,this._answer=void 0;break;case b.HaveLocalOffer:this._signalingState=b.Stable,this._answer=t;break;case b.HaveRemoteOffer:break;case b.Closed:break;default:throw new Error("Unexpected signaling state.")}if(e instanceof he)switch(this._signalingState){case b.Initial:case b.Stable:this._signalingState=b.HaveLocalOffer,this._offer=t,this._answer=void 0;break;case b.HaveLocalOffer:break;case b.HaveRemoteOffer:this._signalingState=b.Stable,this._answer=t;break;case b.Closed:break;default:throw new Error("Unexpected signaling state.")}if(nt(e))switch(this._signalingState){case b.Initial:case b.Stable:this._signalingState=b.HaveLocalOffer,this._offer=t,this._answer=void 0;break;case b.HaveLocalOffer:break;case b.HaveRemoteOffer:this._signalingState=b.Stable,this._answer=t;break;case b.Closed:break;default:throw new Error("Unexpected signaling state.")}}}start2xxRetransmissionTimer(){if(this.initialTransaction instanceof U){const e=this.initialTransaction;let t=M.T1;const i=()=>{if(!this.ackWait){this.invite2xxTimer=void 0;return}this.logger.log("No ACK for 2xx response received, attempting retransmission"),e.retransmitAcceptedResponse(),t=Math.min(t*2,M.T2),this.invite2xxTimer=setTimeout(i,t)};this.invite2xxTimer=setTimeout(i,t);const s=()=>{e.state===g.Terminated&&(e.removeStateChangeListener(s),this.invite2xxTimer&&(clearTimeout(this.invite2xxTimer),this.invite2xxTimer=void 0),this.ackWait&&(this.delegate&&this.delegate.onAckTimeout?this.delegate.onAckTimeout():this.bye()))};e.addStateChangeListener(s)}}startReInvite2xxRetransmissionTimer(){if(this.reinviteUserAgentServer&&this.reinviteUserAgentServer.transaction instanceof U){const e=this.reinviteUserAgentServer.transaction;let t=M.T1;const i=()=>{if(!this.reinviteUserAgentServer){this.invite2xxTimer=void 0;return}this.logger.log("No ACK for 2xx response received, attempting retransmission"),e.retransmitAcceptedResponse(),t=Math.min(t*2,M.T2),this.invite2xxTimer=setTimeout(i,t)};this.invite2xxTimer=setTimeout(i,t);const s=()=>{e.state===g.Terminated&&(e.removeStateChangeListener(s),this.invite2xxTimer&&(clearTimeout(this.invite2xxTimer),this.invite2xxTimer=void 0),this.reinviteUserAgentServer)};e.addStateChangeListener(s)}}}class ri extends O{constructor(e,t,i){super(ae,e,t,i),this.confirmedDialogAcks=new Map,this.confirmedDialogs=new Map,this.earlyDialogs=new Map,this.delegate=i}dispose(){this.earlyDialogs.forEach(e=>e.dispose()),this.earlyDialogs.clear(),super.dispose()}onTransportError(e){if(this.transaction.state===g.Calling)return super.onTransportError(e);this.logger.error(e.message),this.logger.error("User agent client request transport error while sending ACK.")}receiveResponse(e){if(!this.authenticationGuard(e))return;const t=e.statusCode?e.statusCode.toString():"";if(!t)throw new Error("Response status code undefined.");switch(!0){case/^100$/.test(t):this.delegate&&this.delegate.onTrying&&this.delegate.onTrying({message:e});return;case/^1[0-9]{2}$/.test(t):{if(!e.toTag){this.logger.warn("Non-100 1xx INVITE response received without a to tag, dropping.");return}if(!e.parseHeader("contact")){this.logger.error("Non-100 1xx INVITE response received without a Contact header field, dropping.");return}const s=we.initialDialogStateForUserAgentClient(this.message,e);let r=this.earlyDialogs.get(s.id);if(!r){const a=this.transaction;if(!(a instanceof ae))throw new Error("Transaction not instance of InviteClientTransaction.");r=new Me(a,this.core,s),this.earlyDialogs.set(r.id,r)}if(!r.reliableSequenceGuard(e)){this.logger.warn("1xx INVITE reliable response received out of order or is a retransmission, dropping.");return}(r.signalingState===b.Initial||r.signalingState===b.HaveLocalOffer)&&r.signalingStateTransition(e);const n=r;this.delegate&&this.delegate.onProgress&&this.delegate.onProgress({message:e,session:n,prack:a=>n.prack(void 0,a)})}return;case/^2[0-9]{2}$/.test(t):{if(!e.toTag){this.logger.error("2xx INVITE response received without a to tag, dropping.");return}if(!e.parseHeader("contact")){this.logger.error("2xx INVITE response received without a Contact header field, dropping.");return}const s=we.initialDialogStateForUserAgentClient(this.message,e);let r=this.confirmedDialogs.get(s.id);if(r){const a=this.confirmedDialogAcks.get(s.id);if(a){const d=this.transaction;if(!(d instanceof ae))throw new Error("Client transaction not instance of InviteClientTransaction.");d.ackResponse(a.message)}return}if(r=this.earlyDialogs.get(s.id),r)r.confirm(),r.recomputeRouteSet(e),this.earlyDialogs.delete(r.id),this.confirmedDialogs.set(r.id,r);else{const a=this.transaction;if(!(a instanceof ae))throw new Error("Transaction not instance of InviteClientTransaction.");r=new Me(a,this.core,s),this.confirmedDialogs.set(r.id,r)}(r.signalingState===b.Initial||r.signalingState===b.HaveLocalOffer)&&r.signalingStateTransition(e);const n=r;if(this.delegate&&this.delegate.onAccept)this.delegate.onAccept({message:e,session:n,ack:a=>{const d=n.ack(a);return this.confirmedDialogAcks.set(n.id,d),d}});else{const a=n.ack();this.confirmedDialogAcks.set(n.id,a)}}return;case/^3[0-9]{2}$/.test(t):this.earlyDialogs.forEach(i=>i.dispose()),this.earlyDialogs.clear(),this.delegate&&this.delegate.onRedirect&&this.delegate.onRedirect({message:e});return;case/^[4-6][0-9]{2}$/.test(t):this.earlyDialogs.forEach(i=>i.dispose()),this.earlyDialogs.clear(),this.delegate&&this.delegate.onReject&&this.delegate.onReject({message:e});return;default:throw new Error(`Invalid status code ${t}`)}}}class Ve extends Z{constructor(e,t,i){super(U,e,t,i),this.core=e}dispose(){this.earlyDialog&&this.earlyDialog.dispose(),super.dispose()}accept(e={statusCode:200}){if(!this.acceptable)throw new re(`${this.message.method} not acceptable in state ${this.transaction.state}.`);if(!this.confirmedDialog)if(this.earlyDialog)this.earlyDialog.confirm(),this.confirmedDialog=this.earlyDialog,this.earlyDialog=void 0;else{const d=this.transaction;if(!(d instanceof U))throw new Error("Transaction not instance of InviteClientTransaction.");const f=we.initialDialogStateForUserAgentServer(this.message,this.toTag);this.confirmedDialog=new Me(d,this.core,f)}const t=this.message.getHeaders("record-route").map(d=>`Record-Route: ${d}`),i=`Contact: ${this.core.configuration.contact.toString()}`,s="Allow: "+ne.toString();if(!e.body){if(this.confirmedDialog.signalingState===b.Stable)e.body=this.confirmedDialog.answer;else if(this.confirmedDialog.signalingState===b.Initial||this.confirmedDialog.signalingState===b.HaveRemoteOffer)throw new Error("Response must have a body.")}e.statusCode=e.statusCode||200,e.extraHeaders=e.extraHeaders||[],e.extraHeaders=e.extraHeaders.concat(t),e.extraHeaders.push(s),e.extraHeaders.push(i);const r=super.accept(e),n=this.confirmedDialog,a=Object.assign(Object.assign({},r),{session:n});return e.body&&this.confirmedDialog.signalingState!==b.Stable&&this.confirmedDialog.signalingStateTransition(e.body),a}progress(e={statusCode:180}){if(!this.progressable)throw new re(`${this.message.method} not progressable in state ${this.transaction.state}.`);if(!this.earlyDialog){const a=this.transaction;if(!(a instanceof U))throw new Error("Transaction not instance of InviteClientTransaction.");const d=we.initialDialogStateForUserAgentServer(this.message,this.toTag,!0);this.earlyDialog=new Me(a,this.core,d)}const t=this.message.getHeaders("record-route").map(a=>`Record-Route: ${a}`),i=`Contact: ${this.core.configuration.contact}`;e.extraHeaders=e.extraHeaders||[],e.extraHeaders=e.extraHeaders.concat(t),e.extraHeaders.push(i);const s=super.progress(e),r=this.earlyDialog,n=Object.assign(Object.assign({},s),{session:r});return e.body&&this.earlyDialog.signalingState!==b.Stable&&this.earlyDialog.signalingStateTransition(e.body),n}redirect(e,t={statusCode:302}){return super.redirect(e,t)}reject(e={statusCode:486}){return super.reject(e)}}class ni extends O{constructor(e,t,i){super(B,e,t,i)}}class oi extends O{constructor(e,t,i){super(B,e,t,i)}}class ai extends Z{constructor(e,t,i){super(j,e,t,i),this.core=e}}class ci extends O{constructor(e,t,i){const s=e.createOutgoingRequestMessage(v.SUBSCRIBE,i);super(B,e.userAgentCore,s,t),this.dialog=e}waitNotifyStop(){}receiveResponse(e){if(e.statusCode&&e.statusCode>=200&&e.statusCode<300){const t=e.getHeader("Expires");if(!t)this.logger.warn("Expires header missing in a 200-class response to SUBSCRIBE");else{const i=Number(t);this.dialog.subscriptionExpires>i&&(this.dialog.subscriptionExpires=i)}}e.statusCode&&e.statusCode>=400&&e.statusCode<700&&[404,405,410,416,480,481,482,483,484,485,489,501,604].includes(e.statusCode)&&this.dialog.terminate(),super.receiveResponse(e)}}class pt extends we{constructor(e,t,i,s,r,n){super(s,r),this.delegate=n,this._autoRefresh=!1,this._subscriptionEvent=e,this._subscriptionExpires=t,this._subscriptionExpiresInitial=t,this._subscriptionExpiresLastSet=Math.floor(Date.now()/1e3),this._subscriptionRefresh=void 0,this._subscriptionRefreshLastSet=void 0,this._subscriptionState=i,this.logger=s.loggerFactory.getLogger("sip.subscribe-dialog"),this.logger.log(`SUBSCRIBE dialog ${this.id} constructed`)}static initialDialogStateForSubscription(e,t){const s=t.getHeaders("record-route"),r=t.parseHeader("contact");if(!r)throw new Error("Contact undefined.");if(!(r instanceof N))throw new Error("Contact not instance of NameAddrHeader.");const n=r.uri,a=e.cseq,d=void 0,f=e.callId,h=e.fromTag,w=t.fromTag;if(!f)throw new Error("Call id undefined.");if(!h)throw new Error("From tag undefined.");if(!w)throw new Error("To tag undefined.");if(!e.from)throw new Error("From undefined.");if(!e.to)throw new Error("To undefined.");const S=e.from.uri,x=e.to.uri;return{id:f+h+w,early:!1,callId:f,localTag:h,remoteTag:w,localSequenceNumber:a,remoteSequenceNumber:d,localURI:S,remoteURI:x,remoteTarget:n,routeSet:s,secure:!1}}dispose(){super.dispose(),this.N&&(clearTimeout(this.N),this.N=void 0),this.refreshTimerClear(),this.logger.log(`SUBSCRIBE dialog ${this.id} destroyed`)}get autoRefresh(){return this._autoRefresh}set autoRefresh(e){this._autoRefresh=!0,this.refreshTimerSet()}get subscriptionEvent(){return this._subscriptionEvent}get subscriptionExpires(){const e=Math.floor(Date.now()/1e3)-this._subscriptionExpiresLastSet,t=this._subscriptionExpires-e;return Math.max(t,0)}set subscriptionExpires(e){if(e<0)throw new Error("Expires must be greater than or equal to zero.");if(this._subscriptionExpires=e,this._subscriptionExpiresLastSet=Math.floor(Date.now()/1e3),this.autoRefresh){const t=this.subscriptionRefresh;(t===void 0||t>=e)&&this.refreshTimerSet()}}get subscriptionExpiresInitial(){return this._subscriptionExpiresInitial}get subscriptionRefresh(){if(this._subscriptionRefresh===void 0||this._subscriptionRefreshLastSet===void 0)return;const e=Math.floor(Date.now()/1e3)-this._subscriptionRefreshLastSet,t=this._subscriptionRefresh-e;return Math.max(t,0)}get subscriptionState(){return this._subscriptionState}receiveRequest(e){if(this.logger.log(`SUBSCRIBE dialog ${this.id} received ${e.method} request`),!this.sequenceGuard(e)){this.logger.log(`SUBSCRIBE dialog ${this.id} rejected out of order ${e.method} request.`);return}super.receiveRequest(e),e.method===v.NOTIFY?this.onNotify(e):(this.logger.log(`SUBSCRIBE dialog ${this.id} received unimplemented ${e.method} request`),this.core.replyStateless(e,{statusCode:501}))}refresh(){const e="Allow: "+ne.toString(),t={};return t.extraHeaders=(t.extraHeaders||[]).slice(),t.extraHeaders.push(e),t.extraHeaders.push("Event: "+this.subscriptionEvent),t.extraHeaders.push("Expires: "+this.subscriptionExpiresInitial),t.extraHeaders.push("Contact: "+this.core.configuration.contact.toString()),this.subscribe(void 0,t)}subscribe(e,t={}){var i;if(this.subscriptionState!==R.Pending&&this.subscriptionState!==R.Active)throw new Error(`Invalid state ${this.subscriptionState}. May only re-subscribe while in state "pending" or "active".`);this.logger.log(`SUBSCRIBE dialog ${this.id} sending SUBSCRIBE request`);const s=new ci(this,e,t);return this.N&&(clearTimeout(this.N),this.N=void 0),!((i=t.extraHeaders)===null||i===void 0)&&i.includes("Expires: 0")||(this.N=setTimeout(()=>this.timerN(),M.TIMER_N)),s}terminate(){this.stateTransition(R.Terminated),this.onTerminated()}unsubscribe(){const e="Allow: "+ne.toString(),t={};return t.extraHeaders=(t.extraHeaders||[]).slice(),t.extraHeaders.push(e),t.extraHeaders.push("Event: "+this.subscriptionEvent),t.extraHeaders.push("Expires: 0"),t.extraHeaders.push("Contact: "+this.core.configuration.contact.toString()),this.subscribe(void 0,t)}onNotify(e){const t=e.parseHeader("Event").event;if(!t||t!==this.subscriptionEvent){this.core.replyStateless(e,{statusCode:489});return}this.N&&(clearTimeout(this.N),this.N=void 0);const i=e.parseHeader("Subscription-State");if(!i||!i.state){this.core.replyStateless(e,{statusCode:489});return}const s=i.state,r=i.expires?Math.max(i.expires,0):void 0;switch(s){case"pending":this.stateTransition(R.Pending,r);break;case"active":this.stateTransition(R.Active,r);break;case"terminated":this.stateTransition(R.Terminated,r);break;default:this.logger.warn("Unrecognized subscription state.");break}const n=new He(this,e);this.delegate&&this.delegate.onNotify?this.delegate.onNotify(n):n.accept()}onRefresh(e){this.delegate&&this.delegate.onRefresh&&this.delegate.onRefresh(e)}onTerminated(){this.delegate&&this.delegate.onTerminated&&this.delegate.onTerminated()}refreshTimerClear(){this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=void 0)}refreshTimerSet(){if(this.refreshTimerClear(),this.autoRefresh&&this.subscriptionExpires>0){const e=this.subscriptionExpires*900;this._subscriptionRefresh=Math.floor(e/1e3),this._subscriptionRefreshLastSet=Math.floor(Date.now()/1e3),this.refreshTimer=setTimeout(()=>{this.refreshTimer=void 0,this._subscriptionRefresh=void 0,this._subscriptionRefreshLastSet=void 0,this.onRefresh(this.refresh())},e)}}stateTransition(e,t){const i=()=>{this.logger.warn(`Invalid subscription state transition from ${this.subscriptionState} to ${e}`)};switch(e){case R.Initial:i();return;case R.NotifyWait:i();return;case R.Pending:if(this.subscriptionState!==R.NotifyWait&&this.subscriptionState!==R.Pending){i();return}break;case R.Active:if(this.subscriptionState!==R.NotifyWait&&this.subscriptionState!==R.Pending&&this.subscriptionState!==R.Active){i();return}break;case R.Terminated:if(this.subscriptionState!==R.NotifyWait&&this.subscriptionState!==R.Pending&&this.subscriptionState!==R.Active){i();return}break;default:i();return}e===R.Pending&&t&&(this.subscriptionExpires=t),e===R.Active&&t&&(this.subscriptionExpires=t),e===R.Terminated&&this.dispose(),this._subscriptionState=e}timerN(){this.logger.warn("Timer N expired for SUBSCRIBE dialog. Timed out waiting for NOTIFY."),this.subscriptionState!==R.Terminated&&(this.stateTransition(R.Terminated),this.onTerminated())}}class di extends O{constructor(e,t,i){const s=t.getHeader("Event");if(!s)throw new Error("Event undefined");const r=t.getHeader("Expires");if(!r)throw new Error("Expires undefined");super(B,e,t,i),this.delegate=i,this.subscriberId=t.callId+t.fromTag+s,this.subscriptionExpiresRequested=this.subscriptionExpires=Number(r),this.subscriptionEvent=s,this.subscriptionState=R.NotifyWait,this.waitNotifyStart()}dispose(){super.dispose()}onNotify(e){const t=e.message.parseHeader("Event").event;if(!t||t!==this.subscriptionEvent){this.logger.warn("Failed to parse event."),e.reject({statusCode:489});return}const i=e.message.parseHeader("Subscription-State");if(!i||!i.state){this.logger.warn("Failed to parse subscription state."),e.reject({statusCode:489});return}const s=i.state;switch(s){case"pending":break;case"active":break;case"terminated":break;default:this.logger.warn(`Invalid subscription state ${s}`),e.reject({statusCode:489});return}if(s!=="terminated"&&!e.message.parseHeader("contact")){this.logger.warn("Failed to parse contact."),e.reject({statusCode:489});return}if(this.dialog)throw new Error("Dialog already created. This implementation only supports install of single subscriptions.");switch(this.waitNotifyStop(),this.subscriptionExpires=i.expires?Math.min(this.subscriptionExpires,Math.max(i.expires,0)):this.subscriptionExpires,s){case"pending":this.subscriptionState=R.Pending;break;case"active":this.subscriptionState=R.Active;break;case"terminated":this.subscriptionState=R.Terminated;break;default:throw new Error(`Unrecognized state ${s}.`)}if(this.subscriptionState!==R.Terminated){const r=pt.initialDialogStateForSubscription(this.message,e.message);this.dialog=new pt(this.subscriptionEvent,this.subscriptionExpires,this.subscriptionState,this.core,r)}if(this.delegate&&this.delegate.onNotify){const r=e,n=this.dialog;this.delegate.onNotify({request:r,subscription:n})}else e.accept()}waitNotifyStart(){this.N||(this.core.subscribers.set(this.subscriberId,this),this.N=setTimeout(()=>this.timerN(),M.TIMER_N))}waitNotifyStop(){this.N&&(this.core.subscribers.delete(this.subscriberId),clearTimeout(this.N),this.N=void 0)}receiveResponse(e){if(this.authenticationGuard(e)){if(e.statusCode&&e.statusCode>=200&&e.statusCode<300){const t=e.getHeader("Expires");if(!t)this.logger.warn("Expires header missing in a 200-class response to SUBSCRIBE");else{const i=Number(t);i>this.subscriptionExpiresRequested&&this.logger.warn("Expires header in a 200-class response to SUBSCRIBE with a higher value than the one in the request"),i<this.subscriptionExpires&&(this.subscriptionExpires=i)}this.dialog&&this.dialog.subscriptionExpires>this.subscriptionExpires&&(this.dialog.subscriptionExpires=this.subscriptionExpires)}e.statusCode&&e.statusCode>=300&&e.statusCode<700&&this.waitNotifyStop(),super.receiveResponse(e)}}timerN(){this.logger.warn("Timer N expired for SUBSCRIBE user agent client. Timed out waiting for NOTIFY."),this.waitNotifyStop(),this.delegate&&this.delegate.onNotifyTimeout&&this.delegate.onNotifyTimeout()}}class li extends Z{constructor(e,t,i){super(j,e,t,i),this.core=e}}const mt=["application/sdp","application/dtmf-relay"];class hi{constructor(e,t={}){this.userAgentClients=new Map,this.userAgentServers=new Map,this.configuration=e,this.delegate=t,this.dialogs=new Map,this.subscribers=new Map,this.logger=e.loggerFactory.getLogger("sip.user-agent-core")}dispose(){this.reset()}reset(){this.dialogs.forEach(e=>e.dispose()),this.dialogs.clear(),this.subscribers.forEach(e=>e.dispose()),this.subscribers.clear(),this.userAgentClients.forEach(e=>e.dispose()),this.userAgentClients.clear(),this.userAgentServers.forEach(e=>e.dispose()),this.userAgentServers.clear()}get loggerFactory(){return this.configuration.loggerFactory}get transport(){const e=this.configuration.transportAccessor();if(!e)throw new Error("Transport undefined.");return e}invite(e,t){return new ri(this,e,t)}message(e,t){return new ut(this,e,t)}publish(e,t){return new ni(this,e,t)}register(e,t){return new oi(this,e,t)}subscribe(e,t){return new di(this,e,t)}request(e,t){return new O(B,this,e,t)}makeOutgoingRequestMessage(e,t,i,s,r,n,a){const d=this.configuration.sipjsId,f=this.configuration.displayName,h=this.configuration.viaForceRport,w=this.configuration.hackViaTcp,S=this.configuration.supportedOptionTags.slice();e===v.REGISTER&&S.push("path","gruu"),e===v.INVITE&&(this.configuration.contact.pubGruu||this.configuration.contact.tempGruu)&&S.push("gruu");const x=this.configuration.routeSet,I=this.configuration.userAgentHeaderFieldValue,E=this.configuration.viaHost,p=Object.assign(Object.assign({},{callIdPrefix:d,forceRport:h,fromDisplayName:f,hackViaTcp:w,optionTags:S,routeSet:x,userAgentString:I,viaHost:E}),r);return new he(e,t,i,s,p,n,a)}receiveIncomingRequestFromTransport(e){this.receiveRequestFromTransport(e)}receiveIncomingResponseFromTransport(e){this.receiveResponseFromTransport(e)}replyStateless(e,t){const i=this.configuration.userAgentHeaderFieldValue,s=this.configuration.supportedOptionTagsResponse;t=Object.assign(Object.assign({},t),{userAgent:i,supported:s});const r=dt(e,t);return this.transport.send(r.message).catch(n=>{n instanceof Error&&this.logger.error(n.message),this.logger.error(`Transport error occurred sending stateless reply to ${e.method} request.`)}),r}receiveRequestFromTransport(e){const t=e.viaBranch,i=this.userAgentServers.get(t);if(e.method===v.ACK&&i&&i.transaction.state===g.Accepted&&i instanceof Ve){this.logger.warn(`Discarding out of dialog ACK after 2xx response sent on transaction ${t}.`);return}if(e.method===v.CANCEL){i?(this.replyStateless(e,{statusCode:200}),i.transaction instanceof U&&i.transaction.state===g.Proceeding&&i instanceof Ve&&i.receiveCancel(e)):this.replyStateless(e,{statusCode:481});return}if(i){i.transaction.receiveRequest(e);return}this.receiveRequest(e)}receiveRequest(e){if(!ne.includes(e.method)){const s="Allow: "+ne.toString();this.replyStateless(e,{statusCode:405,extraHeaders:[s]});return}if(!e.ruri)throw new Error("Request-URI undefined.");if(e.ruri.scheme!=="sip"){this.replyStateless(e,{statusCode:416});return}const t=e.ruri,i=s=>!!s&&s.user===t.user;if(!i(this.configuration.aor)&&!(i(this.configuration.contact.uri)||i(this.configuration.contact.pubGruu)||i(this.configuration.contact.tempGruu))){this.logger.warn("Request-URI does not point to us."),e.method!==v.ACK&&this.replyStateless(e,{statusCode:404});return}if(e.method===v.INVITE&&!e.hasHeader("Contact")){this.replyStateless(e,{statusCode:400,reasonPhrase:"Missing Contact Header"});return}if(!e.toTag){const s=e.viaBranch;if(!this.userAgentServers.has(s)&&Array.from(this.userAgentServers.values()).some(n=>n.transaction.request.fromTag===e.fromTag&&n.transaction.request.callId===e.callId&&n.transaction.request.cseq===e.cseq)){this.replyStateless(e,{statusCode:482});return}}e.toTag?this.receiveInsideDialogRequest(e):this.receiveOutsideDialogRequest(e)}receiveInsideDialogRequest(e){if(e.method===v.NOTIFY){const s=e.parseHeader("Event");if(!s||!s.event){this.replyStateless(e,{statusCode:489});return}const r=e.callId+e.toTag+s.event,n=this.subscribers.get(r);if(n){const a=new He(this,e);n.onNotify(a);return}}const t=e.callId+e.toTag+e.fromTag,i=this.dialogs.get(t);if(i){if(e.method===v.OPTIONS){const s="Allow: "+ne.toString(),r="Accept: "+mt.toString();this.replyStateless(e,{statusCode:200,extraHeaders:[s,r]});return}i.receiveRequest(e);return}e.method!==v.ACK&&this.replyStateless(e,{statusCode:481})}receiveOutsideDialogRequest(e){switch(e.method){case v.ACK:break;case v.BYE:this.replyStateless(e,{statusCode:481});break;case v.CANCEL:throw new Error(`Unexpected out of dialog request method ${e.method}.`);case v.INFO:this.replyStateless(e,{statusCode:405});break;case v.INVITE:{const t=new Ve(this,e);this.delegate.onInvite?this.delegate.onInvite(t):t.reject()}break;case v.MESSAGE:{const t=new gt(this,e);this.delegate.onMessage?this.delegate.onMessage(t):t.accept()}break;case v.NOTIFY:{const t=new He(this,e);this.delegate.onNotify?this.delegate.onNotify(t):t.reject({statusCode:405})}break;case v.OPTIONS:{const t="Allow: "+ne.toString(),i="Accept: "+mt.toString();this.replyStateless(e,{statusCode:200,extraHeaders:[t,i]})}break;case v.REFER:{const t=new ft(this,e);this.delegate.onRefer?this.delegate.onRefer(t):t.reject({statusCode:405})}break;case v.REGISTER:{const t=new ai(this,e);this.delegate.onRegister?this.delegate.onRegister(t):t.reject({statusCode:405})}break;case v.SUBSCRIBE:{const t=new li(this,e);this.delegate.onSubscribe?this.delegate.onSubscribe(t):t.reject({statusCode:480})}break;default:throw new Error(`Unexpected out of dialog request method ${e.method}.`)}}receiveResponseFromTransport(e){if(e.getHeaders("via").length>1){this.logger.warn("More than one Via header field present in the response, dropping");return}const t=e.viaBranch+e.method,i=this.userAgentClients.get(t);i?i.transaction.receiveResponse(e):this.logger.warn(`Discarding unmatched ${e.statusCode} response to ${e.method} ${t}.`)}}function ui(){return o=>!o.audio&&!o.video?Promise.resolve(new MediaStream):navigator.mediaDevices===void 0?Promise.reject(new Error("Media devices not available in insecure contexts.")):navigator.mediaDevices.getUserMedia.call(navigator.mediaDevices,o)}function gi(){return{bundlePolicy:"balanced",certificates:void 0,iceCandidatePoolSize:0,iceServers:[{urls:"stun:stun.l.google.com:19302"}],iceTransportPolicy:"all",rtcpMuxPolicy:"require"}}class F{constructor(e,t,i){e.debug("SessionDescriptionHandler.constructor"),this.logger=e,this.mediaStreamFactory=t,this.sessionDescriptionHandlerConfiguration=i,this._localMediaStream=new MediaStream,this._remoteMediaStream=new MediaStream,this._peerConnection=new RTCPeerConnection(i?.peerConnectionConfiguration),this.initPeerConnectionEventHandlers()}get localMediaStream(){return this._localMediaStream}get remoteMediaStream(){return this._remoteMediaStream}get dataChannel(){return this._dataChannel}get peerConnection(){return this._peerConnection}get peerConnectionDelegate(){return this._peerConnectionDelegate}set peerConnectionDelegate(e){this._peerConnectionDelegate=e}static dispatchAddTrackEvent(e,t){e.dispatchEvent(new MediaStreamTrackEvent("addtrack",{track:t}))}static dispatchRemoveTrackEvent(e,t){e.dispatchEvent(new MediaStreamTrackEvent("removetrack",{track:t}))}close(){this.logger.debug("SessionDescriptionHandler.close"),this._peerConnection!==void 0&&(this._peerConnection.getReceivers().forEach(e=>{e.track&&e.track.stop()}),this._peerConnection.getSenders().forEach(e=>{e.track&&e.track.stop()}),this._dataChannel&&this._dataChannel.close(),this._peerConnection.close(),this._peerConnection=void 0)}enableReceiverTracks(e){const t=this.peerConnection;if(!t)throw new Error("Peer connection closed.");t.getReceivers().forEach(i=>{i.track&&(i.track.enabled=e)})}enableSenderTracks(e){const t=this.peerConnection;if(!t)throw new Error("Peer connection closed.");t.getSenders().forEach(i=>{i.track&&(i.track.enabled=e)})}getDescription(e,t){var i,s;if(this.logger.debug("SessionDescriptionHandler.getDescription"),this._peerConnection===void 0)return Promise.reject(new Error("Peer connection closed."));this.onDataChannel=e?.onDataChannel;const r=(i=e?.offerOptions)===null||i===void 0?void 0:i.iceRestart,n=e?.iceGatheringTimeout===void 0?(s=this.sessionDescriptionHandlerConfiguration)===null||s===void 0?void 0:s.iceGatheringTimeout:e?.iceGatheringTimeout;return this.getLocalMediaStream(e).then(()=>this.updateDirection(e)).then(()=>this.createDataChannel(e)).then(()=>this.createLocalOfferOrAnswer(e)).then(a=>this.applyModifiers(a,t)).then(a=>this.setLocalSessionDescription(a)).then(()=>this.waitForIceGatheringComplete(r,n)).then(()=>this.getLocalSessionDescription()).then(a=>({body:a.sdp,contentType:"application/sdp"})).catch(a=>{throw this.logger.error("SessionDescriptionHandler.getDescription failed - "+a),a})}hasDescription(e){return this.logger.debug("SessionDescriptionHandler.hasDescription"),e==="application/sdp"}iceGatheringComplete(){this.logger.debug("SessionDescriptionHandler.iceGatheringComplete"),this.iceGatheringCompleteTimeoutId!==void 0&&(this.logger.debug("SessionDescriptionHandler.iceGatheringComplete - clearing timeout"),clearTimeout(this.iceGatheringCompleteTimeoutId),this.iceGatheringCompleteTimeoutId=void 0),this.iceGatheringCompletePromise!==void 0&&(this.logger.debug("SessionDescriptionHandler.iceGatheringComplete - resolving promise"),this.iceGatheringCompleteResolve&&this.iceGatheringCompleteResolve(),this.iceGatheringCompletePromise=void 0,this.iceGatheringCompleteResolve=void 0,this.iceGatheringCompleteReject=void 0)}sendDtmf(e,t){if(this.logger.debug("SessionDescriptionHandler.sendDtmf"),this._peerConnection===void 0)return this.logger.error("SessionDescriptionHandler.sendDtmf failed - peer connection closed"),!1;const i=this._peerConnection.getSenders();if(i.length===0)return this.logger.error("SessionDescriptionHandler.sendDtmf failed - no senders"),!1;const s=i[0].dtmf;if(!s)return this.logger.error("SessionDescriptionHandler.sendDtmf failed - no DTMF sender"),!1;const r=t?.duration,n=t?.interToneGap;try{s.insertDTMF(e,r,n)}catch(a){return this.logger.error(a.toString()),!1}return this.logger.log("SessionDescriptionHandler.sendDtmf sent via RTP: "+e.toString()),!0}setDescription(e,t,i){if(this.logger.debug("SessionDescriptionHandler.setDescription"),this._peerConnection===void 0)return Promise.reject(new Error("Peer connection closed."));this.onDataChannel=t?.onDataChannel;const s=this._peerConnection.signalingState==="have-local-offer"?"answer":"offer";return this.getLocalMediaStream(t).then(()=>this.applyModifiers({sdp:e,type:s},i)).then(r=>this.setRemoteSessionDescription(r)).catch(r=>{throw this.logger.error("SessionDescriptionHandler.setDescription failed - "+r),r})}applyModifiers(e,t){return this.logger.debug("SessionDescriptionHandler.applyModifiers"),!t||t.length===0?Promise.resolve(e):t.reduce((i,s)=>i.then(s),Promise.resolve(e)).then(i=>{if(this.logger.debug("SessionDescriptionHandler.applyModifiers - modified sdp"),!i.sdp||!i.type)throw new Error("Invalid SDP.");return{sdp:i.sdp,type:i.type}})}createDataChannel(e){if(this._peerConnection===void 0)return Promise.reject(new Error("Peer connection closed."));if(e?.dataChannel!==!0||this._dataChannel)return Promise.resolve();switch(this._peerConnection.signalingState){case"stable":this.logger.debug("SessionDescriptionHandler.createDataChannel - creating data channel");try{return this._dataChannel=this._peerConnection.createDataChannel(e?.dataChannelLabel||"",e?.dataChannelOptions),this.onDataChannel&&this.onDataChannel(this._dataChannel),Promise.resolve()}catch(t){return Promise.reject(t)}case"have-remote-offer":return Promise.resolve();default:return Promise.reject(new Error("Invalid signaling state "+this._peerConnection.signalingState))}}createLocalOfferOrAnswer(e){if(this._peerConnection===void 0)return Promise.reject(new Error("Peer connection closed."));switch(this._peerConnection.signalingState){case"stable":return this.logger.debug("SessionDescriptionHandler.createLocalOfferOrAnswer - creating SDP offer"),this._peerConnection.createOffer(e?.offerOptions);case"have-remote-offer":return this.logger.debug("SessionDescriptionHandler.createLocalOfferOrAnswer - creating SDP answer"),this._peerConnection.createAnswer(e?.answerOptions);default:return Promise.reject(new Error("Invalid signaling state "+this._peerConnection.signalingState))}}getLocalMediaStream(e){if(this.logger.debug("SessionDescriptionHandler.getLocalMediaStream"),this._peerConnection===void 0)return Promise.reject(new Error("Peer connection closed."));let t=Object.assign({},e?.constraints);if(this.localMediaStreamConstraints){if(t.audio=t.audio||this.localMediaStreamConstraints.audio,t.video=t.video||this.localMediaStreamConstraints.video,JSON.stringify(this.localMediaStreamConstraints.audio)===JSON.stringify(t.audio)&&JSON.stringify(this.localMediaStreamConstraints.video)===JSON.stringify(t.video))return Promise.resolve()}else t.audio===void 0&&t.video===void 0&&(t={audio:!0});return this.localMediaStreamConstraints=t,this.mediaStreamFactory(t,this,e).then(i=>this.setLocalMediaStream(i))}setLocalMediaStream(e){if(this.logger.debug("SessionDescriptionHandler.setLocalMediaStream"),!this._peerConnection)throw new Error("Peer connection undefined.");const t=this._peerConnection,i=this._localMediaStream,s=[],r=d=>{const f=d.kind;if(f!=="audio"&&f!=="video")throw new Error(`Unknown new track kind ${f}.`);const h=t.getSenders().find(w=>w.track&&w.track.kind===f);h?s.push(new Promise(w=>{this.logger.debug(`SessionDescriptionHandler.setLocalMediaStream - replacing sender ${f} track`),w()}).then(()=>h.replaceTrack(d).then(()=>{const w=i.getTracks().find(S=>S.kind===f);w&&(w.stop(),i.removeTrack(w),F.dispatchRemoveTrackEvent(i,w)),i.addTrack(d),F.dispatchAddTrackEvent(i,d)}).catch(w=>{throw this.logger.error(`SessionDescriptionHandler.setLocalMediaStream - failed to replace sender ${f} track`),w}))):s.push(new Promise(w=>{this.logger.debug(`SessionDescriptionHandler.setLocalMediaStream - adding sender ${f} track`),w()}).then(()=>{try{t.addTrack(d,i)}catch(w){throw this.logger.error(`SessionDescriptionHandler.setLocalMediaStream - failed to add sender ${f} track`),w}i.addTrack(d),F.dispatchAddTrackEvent(i,d)}))},n=e.getAudioTracks();n.length&&r(n[0]);const a=e.getVideoTracks();return a.length&&r(a[0]),s.reduce((d,f)=>d.then(()=>f),Promise.resolve())}getLocalSessionDescription(){if(this.logger.debug("SessionDescriptionHandler.getLocalSessionDescription"),this._peerConnection===void 0)return Promise.reject(new Error("Peer connection closed."));const e=this._peerConnection.localDescription;return e?Promise.resolve(e):Promise.reject(new Error("Failed to get local session description"))}setLocalSessionDescription(e){return this.logger.debug("SessionDescriptionHandler.setLocalSessionDescription"),this._peerConnection===void 0?Promise.reject(new Error("Peer connection closed.")):this._peerConnection.setLocalDescription(e)}setRemoteSessionDescription(e){if(this.logger.debug("SessionDescriptionHandler.setRemoteSessionDescription"),this._peerConnection===void 0)return Promise.reject(new Error("Peer connection closed."));const t=e.sdp;let i;switch(this._peerConnection.signalingState){case"stable":i="offer";break;case"have-local-offer":i="answer";break;default:return Promise.reject(new Error("Invalid signaling state "+this._peerConnection.signalingState))}return t?this._peerConnection.setRemoteDescription({sdp:t,type:i}):(this.logger.error("SessionDescriptionHandler.setRemoteSessionDescription failed - cannot set null sdp"),Promise.reject(new Error("SDP is undefined")))}setRemoteTrack(e){this.logger.debug("SessionDescriptionHandler.setRemoteTrack");const t=this._remoteMediaStream;t.getTrackById(e.id)?this.logger.debug(`SessionDescriptionHandler.setRemoteTrack - have remote ${e.kind} track`):e.kind==="audio"?(this.logger.debug(`SessionDescriptionHandler.setRemoteTrack - adding remote ${e.kind} track`),t.getAudioTracks().forEach(i=>{i.stop(),t.removeTrack(i),F.dispatchRemoveTrackEvent(t,i)}),t.addTrack(e),F.dispatchAddTrackEvent(t,e)):e.kind==="video"&&(this.logger.debug(`SessionDescriptionHandler.setRemoteTrack - adding remote ${e.kind} track`),t.getVideoTracks().forEach(i=>{i.stop(),t.removeTrack(i),F.dispatchRemoveTrackEvent(t,i)}),t.addTrack(e),F.dispatchAddTrackEvent(t,e))}updateDirection(e){if(this._peerConnection===void 0)return Promise.reject(new Error("Peer connection closed."));switch(this._peerConnection.signalingState){case"stable":this.logger.debug("SessionDescriptionHandler.updateDirection - setting offer direction");{const t=i=>{switch(i){case"inactive":return e?.hold?"inactive":"recvonly";case"recvonly":return e?.hold?"inactive":"recvonly";case"sendonly":return e?.hold?"sendonly":"sendrecv";case"sendrecv":return e?.hold?"sendonly":"sendrecv";case"stopped":return"stopped";default:throw new Error("Should never happen")}};this._peerConnection.getTransceivers().forEach(i=>{if(i.direction){const s=t(i.direction);i.direction!==s&&(i.direction=s)}})}break;case"have-remote-offer":this.logger.debug("SessionDescriptionHandler.updateDirection - setting answer direction");{const t=(()=>{const s=this._peerConnection.remoteDescription;if(!s)throw new Error("Failed to read remote offer");const r=/a=sendrecv\r\n|a=sendonly\r\n|a=recvonly\r\n|a=inactive\r\n/.exec(s.sdp);if(r)switch(r[0]){case`a=inactive\r
|
|
48
|
+
`,this.send(u).catch(h=>{this.logTransportError(h,"Failed to send ACK to non-2xx response.")})}stateTransition(e,t=!1){const i=()=>{throw new Error(`Invalid state transition from ${this.state} to ${e}`)};switch(e){case f.Calling:i();break;case f.Proceeding:this.state!==f.Calling&&i();break;case f.Accepted:case f.Completed:this.state!==f.Calling&&this.state!==f.Proceeding&&i();break;case f.Terminated:this.state!==f.Calling&&this.state!==f.Accepted&&this.state!==f.Completed&&(t||i());break;default:i()}this.B&&(clearTimeout(this.B),this.B=void 0),f.Proceeding,e===f.Completed&&(this.D=setTimeout(()=>this.timerD(),M.TIMER_D)),e===f.Accepted&&(this.M=setTimeout(()=>this.timerM(),M.TIMER_M)),e===f.Terminated&&this.dispose(),this.setState(e)}timerA(){}timerB(){this.logger.debug(`Timer B expired for INVITE client transaction ${this.id}.`),this.state===f.Calling&&(this.onRequestTimeout(),this.stateTransition(f.Terminated))}timerD(){this.logger.debug(`Timer D expired for INVITE client transaction ${this.id}.`),this.state===f.Completed&&this.stateTransition(f.Terminated)}timerM(){this.logger.debug(`Timer M expired for INVITE client transaction ${this.id}.`),this.state===f.Accepted&&this.stateTransition(f.Terminated)}}class O{constructor(e,t,i,s){this.transactionConstructor=e,this.core=t,this.message=i,this.delegate=s,this.challenged=!1,this.stale=!1,this.logger=this.loggerFactory.getLogger("sip.user-agent-client"),this.init()}dispose(){this.transaction.dispose()}get loggerFactory(){return this.core.loggerFactory}get transaction(){if(!this._transaction)throw new Error("Transaction undefined.");return this._transaction}cancel(e,t={}){if(!this.transaction)throw new Error("Transaction undefined.");if(!this.message.to)throw new Error("To undefined.");if(!this.message.from)throw new Error("From undefined.");const i=this.core.makeOutgoingRequestMessage(v.CANCEL,this.message.ruri,this.message.from.uri,this.message.to.uri,{toTag:this.message.toTag,fromTag:this.message.fromTag,callId:this.message.callId,cseq:this.message.cseq},t.extraHeaders);return i.branch=this.message.branch,this.message.headers.Route&&(i.headers.Route=this.message.headers.Route),e&&i.setHeader("Reason",e),this.transaction.state===f.Proceeding?new O(B,this.core,i):this.transaction.addStateChangeListener(()=>{this.transaction&&this.transaction.state===f.Proceeding&&new O(B,this.core,i)},{once:!0}),i}authenticationGuard(e,t){const i=e.statusCode;if(!i)throw new Error("Response status code undefined.");if(i!==401&&i!==407)return!0;let s,r;if(i===401?(s=e.parseHeader("www-authenticate"),r="authorization"):(s=e.parseHeader("proxy-authenticate"),r="proxy-authorization"),!s)return this.logger.warn(i+" with wrong or missing challenge, cannot authenticate"),!0;if(this.challenged&&(this.stale||s.stale!==!0))return this.logger.warn(i+" apparently in authentication loop, cannot authenticate"),!0;if(!this.credentials&&(this.credentials=this.core.configuration.authenticationFactory(),!this.credentials))return this.logger.warn("Unable to obtain credentials, cannot authenticate"),!0;if(!this.credentials.authenticate(this.message,s))return!0;this.challenged=!0,s.stale&&(this.stale=!0);let n=this.message.cseq+=1;return t&&t.localSequenceNumber&&(t.incrementLocalSequenceNumber(),n=this.message.cseq=t.localSequenceNumber),this.message.setHeader("cseq",n+" "+this.message.method),this.message.setHeader(r,this.credentials.toString()),this.init(),!1}onRequestTimeout(){this.logger.warn("User agent client request timed out. Generating internal 408 Request Timeout.");const e=new re;e.statusCode=408,e.reasonPhrase="Request Timeout",this.receiveResponse(e)}onTransportError(e){this.logger.error(e.message),this.logger.error("User agent client request transport error. Generating internal 503 Service Unavailable.");const t=new re;t.statusCode=503,t.reasonPhrase="Service Unavailable",this.receiveResponse(t)}receiveResponse(e){if(!this.authenticationGuard(e))return;const t=e.statusCode?e.statusCode.toString():"";if(!t)throw new Error("Response status code undefined.");switch(!0){case/^100$/.test(t):this.delegate&&this.delegate.onTrying&&this.delegate.onTrying({message:e});break;case/^1[0-9]{2}$/.test(t):this.delegate&&this.delegate.onProgress&&this.delegate.onProgress({message:e});break;case/^2[0-9]{2}$/.test(t):this.delegate&&this.delegate.onAccept&&this.delegate.onAccept({message:e});break;case/^3[0-9]{2}$/.test(t):this.delegate&&this.delegate.onRedirect&&this.delegate.onRedirect({message:e});break;case/^[4-6][0-9]{2}$/.test(t):this.delegate&&this.delegate.onReject&&this.delegate.onReject({message:e});break;default:throw new Error(`Invalid status code ${t}`)}}init(){const e={loggerFactory:this.loggerFactory,onRequestTimeout:()=>this.onRequestTimeout(),onStateChange:s=>{s===f.Terminated&&(this.core.userAgentClients.delete(i),t===this._transaction&&this.dispose())},onTransportError:s=>this.onTransportError(s),receiveResponse:s=>this.receiveResponse(s)},t=new this.transactionConstructor(this.message,this.core.transport,e);this._transaction=t;const i=t.id+t.request.method;this.core.userAgentClients.set(i,this)}}class Kt extends O{constructor(e,t,i){const s=e.createOutgoingRequestMessage(v.BYE,i);super(B,e.userAgentCore,s,t),e.dispose()}}class j extends ut{constructor(e,t,i){super(e,t,i,f.Trying,"sip.transaction.nist")}dispose(){this.J&&(clearTimeout(this.J),this.J=void 0),super.dispose()}get kind(){return"nist"}receiveRequest(e){switch(this.state){case f.Trying:break;case f.Proceeding:if(!this.lastResponse)throw new Error("Last response undefined.");this.send(this.lastResponse).catch(t=>{this.logTransportError(t,"Failed to send retransmission of provisional response.")});break;case f.Completed:if(!this.lastResponse)throw new Error("Last response undefined.");this.send(this.lastResponse).catch(t=>{this.logTransportError(t,"Failed to send retransmission of final response.")});break;case f.Terminated:break;default:throw new Error(`Invalid state ${this.state}`)}}receiveResponse(e,t){if(e<100||e>699)throw new Error(`Invalid status code ${e}`);if(e>100&&e<=199)throw new Error("Provisional response other than 100 not allowed.");switch(this.state){case f.Trying:if(this.lastResponse=t,e>=100&&e<200){this.stateTransition(f.Proceeding),this.send(t).catch(s=>{this.logTransportError(s,"Failed to send provisional response.")});return}if(e>=200&&e<=699){this.stateTransition(f.Completed),this.send(t).catch(s=>{this.logTransportError(s,"Failed to send final response.")});return}break;case f.Proceeding:if(this.lastResponse=t,e>=200&&e<=699){this.stateTransition(f.Completed),this.send(t).catch(s=>{this.logTransportError(s,"Failed to send final response.")});return}break;case f.Completed:return;case f.Terminated:break;default:throw new Error(`Invalid state ${this.state}`)}const i=`Non-INVITE server transaction received unexpected ${e} response from TU while in state ${this.state}.`;throw this.logger.error(i),new Error(i)}onTransportError(e){this.user.onTransportError&&this.user.onTransportError(e),this.stateTransition(f.Terminated,!0)}typeToString(){return"non-INVITE server transaction"}stateTransition(e,t=!1){const i=()=>{throw new Error(`Invalid state transition from ${this.state} to ${e}`)};switch(e){case f.Trying:i();break;case f.Proceeding:this.state!==f.Trying&&i();break;case f.Completed:this.state!==f.Trying&&this.state!==f.Proceeding&&i();break;case f.Terminated:this.state!==f.Proceeding&&this.state!==f.Completed&&(t||i());break;default:i()}e===f.Completed&&(this.J=setTimeout(()=>this.timerJ(),M.TIMER_J)),e===f.Terminated&&this.dispose(),this.setState(e)}timerJ(){this.logger.debug(`Timer J expired for NON-INVITE server transaction ${this.id}.`),this.state===f.Completed&&this.stateTransition(f.Terminated)}}class Z{constructor(e,t,i,s){this.transactionConstructor=e,this.core=t,this.message=i,this.delegate=s,this.logger=this.loggerFactory.getLogger("sip.user-agent-server"),this.toTag=i.toTag?i.toTag:$e(),this.init()}dispose(){this.transaction.dispose()}get loggerFactory(){return this.core.loggerFactory}get transaction(){if(!this._transaction)throw new Error("Transaction undefined.");return this._transaction}accept(e={statusCode:200}){if(!this.acceptable)throw new ne(`${this.message.method} not acceptable in state ${this.transaction.state}.`);const t=e.statusCode;if(t<200||t>299)throw new TypeError(`Invalid statusCode: ${t}`);return this.reply(e)}progress(e={statusCode:180}){if(!this.progressable)throw new ne(`${this.message.method} not progressable in state ${this.transaction.state}.`);const t=e.statusCode;if(t<101||t>199)throw new TypeError(`Invalid statusCode: ${t}`);return this.reply(e)}redirect(e,t={statusCode:302}){if(!this.redirectable)throw new ne(`${this.message.method} not redirectable in state ${this.transaction.state}.`);const i=t.statusCode;if(i<300||i>399)throw new TypeError(`Invalid statusCode: ${i}`);const s=new Array;return e.forEach(n=>s.push(`Contact: ${n.toString()}`)),t.extraHeaders=(t.extraHeaders||[]).concat(s),this.reply(t)}reject(e={statusCode:480}){if(!this.rejectable)throw new ne(`${this.message.method} not rejectable in state ${this.transaction.state}.`);const t=e.statusCode;if(t<400||t>699)throw new TypeError(`Invalid statusCode: ${t}`);return this.reply(e)}trying(e){if(!this.tryingable)throw new ne(`${this.message.method} not tryingable in state ${this.transaction.state}.`);return this.reply({statusCode:100})}receiveCancel(e){this.delegate&&this.delegate.onCancel&&this.delegate.onCancel(e)}get acceptable(){if(this.transaction instanceof U)return this.transaction.state===f.Proceeding||this.transaction.state===f.Accepted;if(this.transaction instanceof j)return this.transaction.state===f.Trying||this.transaction.state===f.Proceeding;throw new Error("Unknown transaction type.")}get progressable(){if(this.transaction instanceof U)return this.transaction.state===f.Proceeding;if(this.transaction instanceof j)return!1;throw new Error("Unknown transaction type.")}get redirectable(){if(this.transaction instanceof U)return this.transaction.state===f.Proceeding;if(this.transaction instanceof j)return this.transaction.state===f.Trying||this.transaction.state===f.Proceeding;throw new Error("Unknown transaction type.")}get rejectable(){if(this.transaction instanceof U)return this.transaction.state===f.Proceeding;if(this.transaction instanceof j)return this.transaction.state===f.Trying||this.transaction.state===f.Proceeding;throw new Error("Unknown transaction type.")}get tryingable(){if(this.transaction instanceof U)return this.transaction.state===f.Proceeding;if(this.transaction instanceof j)return this.transaction.state===f.Trying;throw new Error("Unknown transaction type.")}reply(e){!e.toTag&&e.statusCode!==100&&(e.toTag=this.toTag),e.userAgent=e.userAgent||this.core.configuration.userAgentHeaderFieldValue,e.supported=e.supported||this.core.configuration.supportedOptionTagsResponse;const t=lt(this.message,e);return this.transaction.receiveResponse(e.statusCode,t.message),t}init(){const e={loggerFactory:this.loggerFactory,onStateChange:s=>{s===f.Terminated&&(this.core.userAgentServers.delete(i),this.dispose())},onTransportError:s=>{this.logger.error(s.message),this.delegate&&this.delegate.onTransportError?this.delegate.onTransportError(s):this.logger.error("User agent server response transport error.")}},t=new this.transactionConstructor(this.message,this.core.transport,e);this._transaction=t;const i=t.id;this.core.userAgentServers.set(t.id,this)}}class zt extends Z{constructor(e,t,i){super(j,e.userAgentCore,t,i)}}class Yt extends O{constructor(e,t,i){const s=e.createOutgoingRequestMessage(v.INFO,i);super(B,e.userAgentCore,s,t)}}class Jt extends Z{constructor(e,t,i){super(j,e.userAgentCore,t,i)}}class gt extends O{constructor(e,t,i){super(B,e,t,i)}}class ft extends Z{constructor(e,t,i){super(j,e,t,i)}}class Zt extends O{constructor(e,t,i){const s=e.createOutgoingRequestMessage(v.NOTIFY,i);super(B,e.userAgentCore,s,t)}}function Xt(a){return a.userAgentCore!==void 0}class Me extends Z{constructor(e,t,i){const s=Xt(e)?e.userAgentCore:e;super(j,s,t,i)}}class Qt extends O{constructor(e,t,i){const s=e.createOutgoingRequestMessage(v.PRACK,i);super(B,e.userAgentCore,s,t),e.signalingStateTransition(s)}}class ei extends Z{constructor(e,t,i){super(j,e.userAgentCore,t,i),e.signalingStateTransition(t),this.dialog=e}accept(e={statusCode:200}){return e.body&&this.dialog.signalingStateTransition(e.body),super.accept(e)}}class ti extends O{constructor(e,t,i){const s=e.createOutgoingRequestMessage(v.INVITE,i);super(ce,e.userAgentCore,s,t),this.delegate=t,e.signalingStateTransition(s),e.reinviteUserAgentClient=this,this.dialog=e}receiveResponse(e){if(!this.authenticationGuard(e,this.dialog))return;const t=e.statusCode?e.statusCode.toString():"";if(!t)throw new Error("Response status code undefined.");switch(!0){case/^100$/.test(t):this.delegate&&this.delegate.onTrying&&this.delegate.onTrying({message:e});break;case/^1[0-9]{2}$/.test(t):this.delegate&&this.delegate.onProgress&&this.delegate.onProgress({message:e,session:this.dialog,prack:i=>{throw new Error("Unimplemented.")}});break;case/^2[0-9]{2}$/.test(t):this.dialog.signalingStateTransition(e),this.delegate&&this.delegate.onAccept&&this.delegate.onAccept({message:e,session:this.dialog,ack:i=>this.dialog.ack(i)});break;case/^3[0-9]{2}$/.test(t):this.dialog.signalingStateRollback(),this.dialog.reinviteUserAgentClient=void 0,this.delegate&&this.delegate.onRedirect&&this.delegate.onRedirect({message:e});break;case/^[4-6][0-9]{2}$/.test(t):this.dialog.signalingStateRollback(),this.dialog.reinviteUserAgentClient=void 0,this.delegate&&this.delegate.onReject&&this.delegate.onReject({message:e});break;default:throw new Error(`Invalid status code ${t}`)}}}class ii extends Z{constructor(e,t,i){super(U,e.userAgentCore,t,i),e.reinviteUserAgentServer=this,this.dialog=e}accept(e={statusCode:200}){e.extraHeaders=e.extraHeaders||[],e.extraHeaders=e.extraHeaders.concat(this.dialog.routeSet.map(r=>`Record-Route: ${r}`));const t=super.accept(e),i=this.dialog,s=Object.assign(Object.assign({},t),{session:i});return e.body&&this.dialog.signalingStateTransition(e.body),this.dialog.reConfirm(),s}progress(e={statusCode:180}){const t=super.progress(e),i=this.dialog,s=Object.assign(Object.assign({},t),{session:i});return e.body&&this.dialog.signalingStateTransition(e.body),s}redirect(e,t={statusCode:302}){throw this.dialog.signalingStateRollback(),this.dialog.reinviteUserAgentServer=void 0,new Error("Unimplemented.")}reject(e={statusCode:488}){return this.dialog.signalingStateRollback(),this.dialog.reinviteUserAgentServer=void 0,super.reject(e)}}class si extends O{constructor(e,t,i){const s=e.createOutgoingRequestMessage(v.REFER,i);super(B,e.userAgentCore,s,t)}}function ri(a){return a.userAgentCore!==void 0}class pt extends Z{constructor(e,t,i){const s=ri(e)?e.userAgentCore:e;super(j,s,t,i)}}class qe extends be{constructor(e,t,i,s){super(t,i),this.initialTransaction=e,this._signalingState=y.Initial,this.ackWait=!1,this.ackProcessing=!1,this.delegate=s,e instanceof U&&(this.ackWait=!0),this.early||this.start2xxRetransmissionTimer(),this.signalingStateTransition(e.request),this.logger=t.loggerFactory.getLogger("sip.invite-dialog"),this.logger.log(`INVITE dialog ${this.id} constructed`)}dispose(){super.dispose(),this._signalingState=y.Closed,this._offer=void 0,this._answer=void 0,this.invite2xxTimer&&(clearTimeout(this.invite2xxTimer),this.invite2xxTimer=void 0),this.logger.log(`INVITE dialog ${this.id} destroyed`)}get sessionState(){return this.early?V.Early:this.ackWait?V.AckWait:this._signalingState===y.Closed?V.Terminated:V.Confirmed}get signalingState(){return this._signalingState}get offer(){return this._offer}get answer(){return this._answer}confirm(){this.early&&this.start2xxRetransmissionTimer(),super.confirm()}reConfirm(){this.reinviteUserAgentServer&&this.startReInvite2xxRetransmissionTimer()}ack(e={}){this.logger.log(`INVITE dialog ${this.id} sending ACK request`);let t;if(this.reinviteUserAgentClient){if(!(this.reinviteUserAgentClient.transaction instanceof ce))throw new Error("Transaction not instance of InviteClientTransaction.");t=this.reinviteUserAgentClient.transaction,this.reinviteUserAgentClient=void 0}else{if(!(this.initialTransaction instanceof ce))throw new Error("Initial transaction not instance of InviteClientTransaction.");t=this.initialTransaction}const i=this.createOutgoingRequestMessage(v.ACK,{cseq:t.request.cseq,extraHeaders:e.extraHeaders,body:e.body});return t.ackResponse(i),this.signalingStateTransition(i),{message:i}}bye(e,t){if(this.logger.log(`INVITE dialog ${this.id} sending BYE request`),this.initialTransaction instanceof U){if(this.early)throw new Error("UAS MUST NOT send a BYE on early dialogs.");if(this.ackWait&&this.initialTransaction.state!==f.Terminated)throw new Error("UAS MUST NOT send a BYE on a confirmed dialog until it has received an ACK for its 2xx response or until the server transaction times out.")}return new Kt(this,e,t)}info(e,t){if(this.logger.log(`INVITE dialog ${this.id} sending INFO request`),this.early)throw new Error("Dialog not confirmed.");return new Yt(this,e,t)}invite(e,t){if(this.logger.log(`INVITE dialog ${this.id} sending INVITE request`),this.early)throw new Error("Dialog not confirmed.");if(this.reinviteUserAgentClient)throw new Error("There is an ongoing re-INVITE client transaction.");if(this.reinviteUserAgentServer)throw new Error("There is an ongoing re-INVITE server transaction.");return new ti(this,e,t)}message(e,t){if(this.logger.log(`INVITE dialog ${this.id} sending MESSAGE request`),this.early)throw new Error("Dialog not confirmed.");const i=this.createOutgoingRequestMessage(v.MESSAGE,t);return new gt(this.core,i,e)}notify(e,t){if(this.logger.log(`INVITE dialog ${this.id} sending NOTIFY request`),this.early)throw new Error("Dialog not confirmed.");return new Zt(this,e,t)}prack(e,t){return this.logger.log(`INVITE dialog ${this.id} sending PRACK request`),new Qt(this,e,t)}refer(e,t){if(this.logger.log(`INVITE dialog ${this.id} sending REFER request`),this.early)throw new Error("Dialog not confirmed.");return new si(this,e,t)}receiveRequest(e){if(this.logger.log(`INVITE dialog ${this.id} received ${e.method} request`),e.method===v.ACK){if(this.ackWait){if(this.initialTransaction instanceof ce){this.logger.warn(`INVITE dialog ${this.id} received unexpected ${e.method} request, dropping.`);return}if(this.initialTransaction.request.cseq!==e.cseq){this.logger.warn(`INVITE dialog ${this.id} received unexpected ${e.method} request, dropping.`);return}this.ackWait=!1}else{if(!this.reinviteUserAgentServer){this.logger.warn(`INVITE dialog ${this.id} received unexpected ${e.method} request, dropping.`);return}if(this.reinviteUserAgentServer.transaction.request.cseq!==e.cseq){this.logger.warn(`INVITE dialog ${this.id} received unexpected ${e.method} request, dropping.`);return}this.reinviteUserAgentServer=void 0}if(this.signalingStateTransition(e),this.delegate&&this.delegate.onAck){const t=this.delegate.onAck({message:e});t instanceof Promise&&(this.ackProcessing=!0,t.then(()=>this.ackProcessing=!1).catch(()=>this.ackProcessing=!1))}return}if(!this.sequenceGuard(e)){this.logger.log(`INVITE dialog ${this.id} rejected out of order ${e.method} request.`);return}if(super.receiveRequest(e),e.method===v.INVITE){const t=()=>{const r=this.ackWait?"waiting for initial ACK":"processing initial ACK";this.logger.warn(`INVITE dialog ${this.id} received re-INVITE while ${r}`);let n="RFC 5407 suggests the following to avoid this race condition... ";n+=" Note: Implementation issues are outside the scope of this document,",n+=" but the following tip is provided for avoiding race conditions of",n+=" this type. The caller can delay sending re-INVITE F6 for some period",n+=" of time (2 seconds, perhaps), after which the caller can reasonably",n+=" assume that its ACK has been received. Implementors can decouple the",n+=" actions of the user (e.g., pressing the hold button) from the actions",n+=" of the protocol (the sending of re-INVITE F6), so that the UA can",n+=" behave like this. In this case, it is the implementor's choice as to",n+=" how long to wait. In most cases, such an implementation may be",n+=" useful to prevent the type of race condition shown in this section.",n+=" This document expresses no preference about whether or not they",n+=" should wait for an ACK to be delivered. After considering the impact",n+=" on user experience, implementors should decide whether or not to wait",n+=" for a while, because the user experience depends on the",n+=" implementation and has no direct bearing on protocol behavior.",this.logger.warn(n)},s=[`Retry-After: ${Math.floor(Math.random()*10)+1}`];if(this.ackProcessing){this.core.replyStateless(e,{statusCode:500,extraHeaders:s}),t();return}if(this.ackWait&&this.signalingState!==y.Stable){this.core.replyStateless(e,{statusCode:500,extraHeaders:s}),t();return}if(this.reinviteUserAgentServer){this.core.replyStateless(e,{statusCode:500,extraHeaders:s});return}if(this.reinviteUserAgentClient){this.core.replyStateless(e,{statusCode:491});return}}if(e.method===v.INVITE){const t=e.parseHeader("contact");if(!t)throw new Error("Contact undefined.");if(!(t instanceof N))throw new Error("Contact not instance of NameAddrHeader.");this.dialogState.remoteTarget=t.uri}switch(e.method){case v.BYE:{const t=new zt(this,e);this.delegate&&this.delegate.onBye?this.delegate.onBye(t):t.accept(),this.dispose()}break;case v.INFO:{const t=new Jt(this,e);this.delegate&&this.delegate.onInfo?this.delegate.onInfo(t):t.reject({statusCode:469,extraHeaders:["Recv-Info:"]})}break;case v.INVITE:{const t=new ii(this,e);this.signalingStateTransition(e),this.delegate&&this.delegate.onInvite?this.delegate.onInvite(t):t.reject({statusCode:488})}break;case v.MESSAGE:{const t=new ft(this.core,e);this.delegate&&this.delegate.onMessage?this.delegate.onMessage(t):t.accept()}break;case v.NOTIFY:{const t=new Me(this,e);this.delegate&&this.delegate.onNotify?this.delegate.onNotify(t):t.accept()}break;case v.PRACK:{const t=new ei(this,e);this.delegate&&this.delegate.onPrack?this.delegate.onPrack(t):t.accept()}break;case v.REFER:{const t=new pt(this,e);this.delegate&&this.delegate.onRefer?this.delegate.onRefer(t):t.reject()}break;default:this.logger.log(`INVITE dialog ${this.id} received unimplemented ${e.method} request`),this.core.replyStateless(e,{statusCode:501});break}}reliableSequenceGuard(e){const t=e.statusCode;if(!t)throw new Error("Status code undefined");if(t>100&&t<200){const i=e.getHeader("require"),s=e.getHeader("rseq"),r=i&&i.includes("100rel")&&s?Number(s):void 0;if(r){if(this.rseq&&this.rseq+1!==r)return!1;this.rseq=this.rseq?this.rseq+1:r}}return!0}signalingStateRollback(){(this._signalingState===y.HaveLocalOffer||this.signalingState===y.HaveRemoteOffer)&&this._rollbackOffer&&this._rollbackAnswer&&(this._signalingState=y.Stable,this._offer=this._rollbackOffer,this._answer=this._rollbackAnswer)}signalingStateTransition(e){const t=Ee(e);if(!(!t||t.contentDisposition!=="session")){if(this._signalingState===y.Stable&&(this._rollbackOffer=this._offer,this._rollbackAnswer=this._answer),e instanceof me)switch(this._signalingState){case y.Initial:case y.Stable:this._signalingState=y.HaveRemoteOffer,this._offer=t,this._answer=void 0;break;case y.HaveLocalOffer:this._signalingState=y.Stable,this._answer=t;break;case y.HaveRemoteOffer:break;case y.Closed:break;default:throw new Error("Unexpected signaling state.")}if(e instanceof re)switch(this._signalingState){case y.Initial:case y.Stable:this._signalingState=y.HaveRemoteOffer,this._offer=t,this._answer=void 0;break;case y.HaveLocalOffer:this._signalingState=y.Stable,this._answer=t;break;case y.HaveRemoteOffer:break;case y.Closed:break;default:throw new Error("Unexpected signaling state.")}if(e instanceof ge)switch(this._signalingState){case y.Initial:case y.Stable:this._signalingState=y.HaveLocalOffer,this._offer=t,this._answer=void 0;break;case y.HaveLocalOffer:break;case y.HaveRemoteOffer:this._signalingState=y.Stable,this._answer=t;break;case y.Closed:break;default:throw new Error("Unexpected signaling state.")}if(at(e))switch(this._signalingState){case y.Initial:case y.Stable:this._signalingState=y.HaveLocalOffer,this._offer=t,this._answer=void 0;break;case y.HaveLocalOffer:break;case y.HaveRemoteOffer:this._signalingState=y.Stable,this._answer=t;break;case y.Closed:break;default:throw new Error("Unexpected signaling state.")}}}start2xxRetransmissionTimer(){if(this.initialTransaction instanceof U){const e=this.initialTransaction;let t=M.T1;const i=()=>{if(!this.ackWait){this.invite2xxTimer=void 0;return}this.logger.log("No ACK for 2xx response received, attempting retransmission"),e.retransmitAcceptedResponse(),t=Math.min(t*2,M.T2),this.invite2xxTimer=setTimeout(i,t)};this.invite2xxTimer=setTimeout(i,t);const s=()=>{e.state===f.Terminated&&(e.removeStateChangeListener(s),this.invite2xxTimer&&(clearTimeout(this.invite2xxTimer),this.invite2xxTimer=void 0),this.ackWait&&(this.delegate&&this.delegate.onAckTimeout?this.delegate.onAckTimeout():this.bye()))};e.addStateChangeListener(s)}}startReInvite2xxRetransmissionTimer(){if(this.reinviteUserAgentServer&&this.reinviteUserAgentServer.transaction instanceof U){const e=this.reinviteUserAgentServer.transaction;let t=M.T1;const i=()=>{if(!this.reinviteUserAgentServer){this.invite2xxTimer=void 0;return}this.logger.log("No ACK for 2xx response received, attempting retransmission"),e.retransmitAcceptedResponse(),t=Math.min(t*2,M.T2),this.invite2xxTimer=setTimeout(i,t)};this.invite2xxTimer=setTimeout(i,t);const s=()=>{e.state===f.Terminated&&(e.removeStateChangeListener(s),this.invite2xxTimer&&(clearTimeout(this.invite2xxTimer),this.invite2xxTimer=void 0),this.reinviteUserAgentServer)};e.addStateChangeListener(s)}}}class ni extends O{constructor(e,t,i){super(ce,e,t,i),this.confirmedDialogAcks=new Map,this.confirmedDialogs=new Map,this.earlyDialogs=new Map,this.delegate=i}dispose(){this.earlyDialogs.forEach(e=>e.dispose()),this.earlyDialogs.clear(),super.dispose()}onTransportError(e){if(this.transaction.state===f.Calling)return super.onTransportError(e);this.logger.error(e.message),this.logger.error("User agent client request transport error while sending ACK.")}receiveResponse(e){if(!this.authenticationGuard(e))return;const t=e.statusCode?e.statusCode.toString():"";if(!t)throw new Error("Response status code undefined.");switch(!0){case/^100$/.test(t):this.delegate&&this.delegate.onTrying&&this.delegate.onTrying({message:e});return;case/^1[0-9]{2}$/.test(t):{if(!e.toTag){this.logger.warn("Non-100 1xx INVITE response received without a to tag, dropping.");return}if(!e.parseHeader("contact")){this.logger.error("Non-100 1xx INVITE response received without a Contact header field, dropping.");return}const s=be.initialDialogStateForUserAgentClient(this.message,e);let r=this.earlyDialogs.get(s.id);if(!r){const o=this.transaction;if(!(o instanceof ce))throw new Error("Transaction not instance of InviteClientTransaction.");r=new qe(o,this.core,s),this.earlyDialogs.set(r.id,r)}if(!r.reliableSequenceGuard(e)){this.logger.warn("1xx INVITE reliable response received out of order or is a retransmission, dropping.");return}(r.signalingState===y.Initial||r.signalingState===y.HaveLocalOffer)&&r.signalingStateTransition(e);const n=r;this.delegate&&this.delegate.onProgress&&this.delegate.onProgress({message:e,session:n,prack:o=>n.prack(void 0,o)})}return;case/^2[0-9]{2}$/.test(t):{if(!e.toTag){this.logger.error("2xx INVITE response received without a to tag, dropping.");return}if(!e.parseHeader("contact")){this.logger.error("2xx INVITE response received without a Contact header field, dropping.");return}const s=be.initialDialogStateForUserAgentClient(this.message,e);let r=this.confirmedDialogs.get(s.id);if(r){const o=this.confirmedDialogAcks.get(s.id);if(o){const d=this.transaction;if(!(d instanceof ce))throw new Error("Client transaction not instance of InviteClientTransaction.");d.ackResponse(o.message)}return}if(r=this.earlyDialogs.get(s.id),r)r.confirm(),r.recomputeRouteSet(e),this.earlyDialogs.delete(r.id),this.confirmedDialogs.set(r.id,r);else{const o=this.transaction;if(!(o instanceof ce))throw new Error("Transaction not instance of InviteClientTransaction.");r=new qe(o,this.core,s),this.confirmedDialogs.set(r.id,r)}(r.signalingState===y.Initial||r.signalingState===y.HaveLocalOffer)&&r.signalingStateTransition(e);const n=r;if(this.delegate&&this.delegate.onAccept)this.delegate.onAccept({message:e,session:n,ack:o=>{const d=n.ack(o);return this.confirmedDialogAcks.set(n.id,d),d}});else{const o=n.ack();this.confirmedDialogAcks.set(n.id,o)}}return;case/^3[0-9]{2}$/.test(t):this.earlyDialogs.forEach(i=>i.dispose()),this.earlyDialogs.clear(),this.delegate&&this.delegate.onRedirect&&this.delegate.onRedirect({message:e});return;case/^[4-6][0-9]{2}$/.test(t):this.earlyDialogs.forEach(i=>i.dispose()),this.earlyDialogs.clear(),this.delegate&&this.delegate.onReject&&this.delegate.onReject({message:e});return;default:throw new Error(`Invalid status code ${t}`)}}}class Ve extends Z{constructor(e,t,i){super(U,e,t,i),this.core=e}dispose(){this.earlyDialog&&this.earlyDialog.dispose(),super.dispose()}accept(e={statusCode:200}){if(!this.acceptable)throw new ne(`${this.message.method} not acceptable in state ${this.transaction.state}.`);if(!this.confirmedDialog)if(this.earlyDialog)this.earlyDialog.confirm(),this.confirmedDialog=this.earlyDialog,this.earlyDialog=void 0;else{const d=this.transaction;if(!(d instanceof U))throw new Error("Transaction not instance of InviteClientTransaction.");const u=be.initialDialogStateForUserAgentServer(this.message,this.toTag);this.confirmedDialog=new qe(d,this.core,u)}const t=this.message.getHeaders("record-route").map(d=>`Record-Route: ${d}`),i=`Contact: ${this.core.configuration.contact.toString()}`,s="Allow: "+ae.toString();if(!e.body){if(this.confirmedDialog.signalingState===y.Stable)e.body=this.confirmedDialog.answer;else if(this.confirmedDialog.signalingState===y.Initial||this.confirmedDialog.signalingState===y.HaveRemoteOffer)throw new Error("Response must have a body.")}e.statusCode=e.statusCode||200,e.extraHeaders=e.extraHeaders||[],e.extraHeaders=e.extraHeaders.concat(t),e.extraHeaders.push(s),e.extraHeaders.push(i);const r=super.accept(e),n=this.confirmedDialog,o=Object.assign(Object.assign({},r),{session:n});return e.body&&this.confirmedDialog.signalingState!==y.Stable&&this.confirmedDialog.signalingStateTransition(e.body),o}progress(e={statusCode:180}){if(!this.progressable)throw new ne(`${this.message.method} not progressable in state ${this.transaction.state}.`);if(!this.earlyDialog){const o=this.transaction;if(!(o instanceof U))throw new Error("Transaction not instance of InviteClientTransaction.");const d=be.initialDialogStateForUserAgentServer(this.message,this.toTag,!0);this.earlyDialog=new qe(o,this.core,d)}const t=this.message.getHeaders("record-route").map(o=>`Record-Route: ${o}`),i=`Contact: ${this.core.configuration.contact}`;e.extraHeaders=e.extraHeaders||[],e.extraHeaders=e.extraHeaders.concat(t),e.extraHeaders.push(i);const s=super.progress(e),r=this.earlyDialog,n=Object.assign(Object.assign({},s),{session:r});return e.body&&this.earlyDialog.signalingState!==y.Stable&&this.earlyDialog.signalingStateTransition(e.body),n}redirect(e,t={statusCode:302}){return super.redirect(e,t)}reject(e={statusCode:486}){return super.reject(e)}}class ai extends O{constructor(e,t,i){super(B,e,t,i)}}class oi extends O{constructor(e,t,i){super(B,e,t,i)}}class ci extends Z{constructor(e,t,i){super(j,e,t,i),this.core=e}}class di extends O{constructor(e,t,i){const s=e.createOutgoingRequestMessage(v.SUBSCRIBE,i);super(B,e.userAgentCore,s,t),this.dialog=e}waitNotifyStop(){}receiveResponse(e){if(e.statusCode&&e.statusCode>=200&&e.statusCode<300){const t=e.getHeader("Expires");if(!t)this.logger.warn("Expires header missing in a 200-class response to SUBSCRIBE");else{const i=Number(t);this.dialog.subscriptionExpires>i&&(this.dialog.subscriptionExpires=i)}}e.statusCode&&e.statusCode>=400&&e.statusCode<700&&[404,405,410,416,480,481,482,483,484,485,489,501,604].includes(e.statusCode)&&this.dialog.terminate(),super.receiveResponse(e)}}class mt extends be{constructor(e,t,i,s,r,n){super(s,r),this.delegate=n,this._autoRefresh=!1,this._subscriptionEvent=e,this._subscriptionExpires=t,this._subscriptionExpiresInitial=t,this._subscriptionExpiresLastSet=Math.floor(Date.now()/1e3),this._subscriptionRefresh=void 0,this._subscriptionRefreshLastSet=void 0,this._subscriptionState=i,this.logger=s.loggerFactory.getLogger("sip.subscribe-dialog"),this.logger.log(`SUBSCRIBE dialog ${this.id} constructed`)}static initialDialogStateForSubscription(e,t){const s=t.getHeaders("record-route"),r=t.parseHeader("contact");if(!r)throw new Error("Contact undefined.");if(!(r instanceof N))throw new Error("Contact not instance of NameAddrHeader.");const n=r.uri,o=e.cseq,d=void 0,u=e.callId,h=e.fromTag,m=t.fromTag;if(!u)throw new Error("Call id undefined.");if(!h)throw new Error("From tag undefined.");if(!m)throw new Error("To tag undefined.");if(!e.from)throw new Error("From undefined.");if(!e.to)throw new Error("To undefined.");const S=e.from.uri,x=e.to.uri;return{id:u+h+m,early:!1,callId:u,localTag:h,remoteTag:m,localSequenceNumber:o,remoteSequenceNumber:d,localURI:S,remoteURI:x,remoteTarget:n,routeSet:s,secure:!1}}dispose(){super.dispose(),this.N&&(clearTimeout(this.N),this.N=void 0),this.refreshTimerClear(),this.logger.log(`SUBSCRIBE dialog ${this.id} destroyed`)}get autoRefresh(){return this._autoRefresh}set autoRefresh(e){this._autoRefresh=!0,this.refreshTimerSet()}get subscriptionEvent(){return this._subscriptionEvent}get subscriptionExpires(){const e=Math.floor(Date.now()/1e3)-this._subscriptionExpiresLastSet,t=this._subscriptionExpires-e;return Math.max(t,0)}set subscriptionExpires(e){if(e<0)throw new Error("Expires must be greater than or equal to zero.");if(this._subscriptionExpires=e,this._subscriptionExpiresLastSet=Math.floor(Date.now()/1e3),this.autoRefresh){const t=this.subscriptionRefresh;(t===void 0||t>=e)&&this.refreshTimerSet()}}get subscriptionExpiresInitial(){return this._subscriptionExpiresInitial}get subscriptionRefresh(){if(this._subscriptionRefresh===void 0||this._subscriptionRefreshLastSet===void 0)return;const e=Math.floor(Date.now()/1e3)-this._subscriptionRefreshLastSet,t=this._subscriptionRefresh-e;return Math.max(t,0)}get subscriptionState(){return this._subscriptionState}receiveRequest(e){if(this.logger.log(`SUBSCRIBE dialog ${this.id} received ${e.method} request`),!this.sequenceGuard(e)){this.logger.log(`SUBSCRIBE dialog ${this.id} rejected out of order ${e.method} request.`);return}super.receiveRequest(e),e.method===v.NOTIFY?this.onNotify(e):(this.logger.log(`SUBSCRIBE dialog ${this.id} received unimplemented ${e.method} request`),this.core.replyStateless(e,{statusCode:501}))}refresh(){const e="Allow: "+ae.toString(),t={};return t.extraHeaders=(t.extraHeaders||[]).slice(),t.extraHeaders.push(e),t.extraHeaders.push("Event: "+this.subscriptionEvent),t.extraHeaders.push("Expires: "+this.subscriptionExpiresInitial),t.extraHeaders.push("Contact: "+this.core.configuration.contact.toString()),this.subscribe(void 0,t)}subscribe(e,t={}){var i;if(this.subscriptionState!==I.Pending&&this.subscriptionState!==I.Active)throw new Error(`Invalid state ${this.subscriptionState}. May only re-subscribe while in state "pending" or "active".`);this.logger.log(`SUBSCRIBE dialog ${this.id} sending SUBSCRIBE request`);const s=new di(this,e,t);return this.N&&(clearTimeout(this.N),this.N=void 0),!((i=t.extraHeaders)===null||i===void 0)&&i.includes("Expires: 0")||(this.N=setTimeout(()=>this.timerN(),M.TIMER_N)),s}terminate(){this.stateTransition(I.Terminated),this.onTerminated()}unsubscribe(){const e="Allow: "+ae.toString(),t={};return t.extraHeaders=(t.extraHeaders||[]).slice(),t.extraHeaders.push(e),t.extraHeaders.push("Event: "+this.subscriptionEvent),t.extraHeaders.push("Expires: 0"),t.extraHeaders.push("Contact: "+this.core.configuration.contact.toString()),this.subscribe(void 0,t)}onNotify(e){const t=e.parseHeader("Event").event;if(!t||t!==this.subscriptionEvent){this.core.replyStateless(e,{statusCode:489});return}this.N&&(clearTimeout(this.N),this.N=void 0);const i=e.parseHeader("Subscription-State");if(!i||!i.state){this.core.replyStateless(e,{statusCode:489});return}const s=i.state,r=i.expires?Math.max(i.expires,0):void 0;switch(s){case"pending":this.stateTransition(I.Pending,r);break;case"active":this.stateTransition(I.Active,r);break;case"terminated":this.stateTransition(I.Terminated,r);break;default:this.logger.warn("Unrecognized subscription state.");break}const n=new Me(this,e);this.delegate&&this.delegate.onNotify?this.delegate.onNotify(n):n.accept()}onRefresh(e){this.delegate&&this.delegate.onRefresh&&this.delegate.onRefresh(e)}onTerminated(){this.delegate&&this.delegate.onTerminated&&this.delegate.onTerminated()}refreshTimerClear(){this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=void 0)}refreshTimerSet(){if(this.refreshTimerClear(),this.autoRefresh&&this.subscriptionExpires>0){const e=this.subscriptionExpires*900;this._subscriptionRefresh=Math.floor(e/1e3),this._subscriptionRefreshLastSet=Math.floor(Date.now()/1e3),this.refreshTimer=setTimeout(()=>{this.refreshTimer=void 0,this._subscriptionRefresh=void 0,this._subscriptionRefreshLastSet=void 0,this.onRefresh(this.refresh())},e)}}stateTransition(e,t){const i=()=>{this.logger.warn(`Invalid subscription state transition from ${this.subscriptionState} to ${e}`)};switch(e){case I.Initial:i();return;case I.NotifyWait:i();return;case I.Pending:if(this.subscriptionState!==I.NotifyWait&&this.subscriptionState!==I.Pending){i();return}break;case I.Active:if(this.subscriptionState!==I.NotifyWait&&this.subscriptionState!==I.Pending&&this.subscriptionState!==I.Active){i();return}break;case I.Terminated:if(this.subscriptionState!==I.NotifyWait&&this.subscriptionState!==I.Pending&&this.subscriptionState!==I.Active){i();return}break;default:i();return}e===I.Pending&&t&&(this.subscriptionExpires=t),e===I.Active&&t&&(this.subscriptionExpires=t),e===I.Terminated&&this.dispose(),this._subscriptionState=e}timerN(){this.logger.warn("Timer N expired for SUBSCRIBE dialog. Timed out waiting for NOTIFY."),this.subscriptionState!==I.Terminated&&(this.stateTransition(I.Terminated),this.onTerminated())}}class li extends O{constructor(e,t,i){const s=t.getHeader("Event");if(!s)throw new Error("Event undefined");const r=t.getHeader("Expires");if(!r)throw new Error("Expires undefined");super(B,e,t,i),this.delegate=i,this.subscriberId=t.callId+t.fromTag+s,this.subscriptionExpiresRequested=this.subscriptionExpires=Number(r),this.subscriptionEvent=s,this.subscriptionState=I.NotifyWait,this.waitNotifyStart()}dispose(){super.dispose()}onNotify(e){const t=e.message.parseHeader("Event").event;if(!t||t!==this.subscriptionEvent){this.logger.warn("Failed to parse event."),e.reject({statusCode:489});return}const i=e.message.parseHeader("Subscription-State");if(!i||!i.state){this.logger.warn("Failed to parse subscription state."),e.reject({statusCode:489});return}const s=i.state;switch(s){case"pending":break;case"active":break;case"terminated":break;default:this.logger.warn(`Invalid subscription state ${s}`),e.reject({statusCode:489});return}if(s!=="terminated"&&!e.message.parseHeader("contact")){this.logger.warn("Failed to parse contact."),e.reject({statusCode:489});return}if(this.dialog)throw new Error("Dialog already created. This implementation only supports install of single subscriptions.");switch(this.waitNotifyStop(),this.subscriptionExpires=i.expires?Math.min(this.subscriptionExpires,Math.max(i.expires,0)):this.subscriptionExpires,s){case"pending":this.subscriptionState=I.Pending;break;case"active":this.subscriptionState=I.Active;break;case"terminated":this.subscriptionState=I.Terminated;break;default:throw new Error(`Unrecognized state ${s}.`)}if(this.subscriptionState!==I.Terminated){const r=mt.initialDialogStateForSubscription(this.message,e.message);this.dialog=new mt(this.subscriptionEvent,this.subscriptionExpires,this.subscriptionState,this.core,r)}if(this.delegate&&this.delegate.onNotify){const r=e,n=this.dialog;this.delegate.onNotify({request:r,subscription:n})}else e.accept()}waitNotifyStart(){this.N||(this.core.subscribers.set(this.subscriberId,this),this.N=setTimeout(()=>this.timerN(),M.TIMER_N))}waitNotifyStop(){this.N&&(this.core.subscribers.delete(this.subscriberId),clearTimeout(this.N),this.N=void 0)}receiveResponse(e){if(this.authenticationGuard(e)){if(e.statusCode&&e.statusCode>=200&&e.statusCode<300){const t=e.getHeader("Expires");if(!t)this.logger.warn("Expires header missing in a 200-class response to SUBSCRIBE");else{const i=Number(t);i>this.subscriptionExpiresRequested&&this.logger.warn("Expires header in a 200-class response to SUBSCRIBE with a higher value than the one in the request"),i<this.subscriptionExpires&&(this.subscriptionExpires=i)}this.dialog&&this.dialog.subscriptionExpires>this.subscriptionExpires&&(this.dialog.subscriptionExpires=this.subscriptionExpires)}e.statusCode&&e.statusCode>=300&&e.statusCode<700&&this.waitNotifyStop(),super.receiveResponse(e)}}timerN(){this.logger.warn("Timer N expired for SUBSCRIBE user agent client. Timed out waiting for NOTIFY."),this.waitNotifyStop(),this.delegate&&this.delegate.onNotifyTimeout&&this.delegate.onNotifyTimeout()}}class hi extends Z{constructor(e,t,i){super(j,e,t,i),this.core=e}}const wt=["application/sdp","application/dtmf-relay"];class ui{constructor(e,t={}){this.userAgentClients=new Map,this.userAgentServers=new Map,this.configuration=e,this.delegate=t,this.dialogs=new Map,this.subscribers=new Map,this.logger=e.loggerFactory.getLogger("sip.user-agent-core")}dispose(){this.reset()}reset(){this.dialogs.forEach(e=>e.dispose()),this.dialogs.clear(),this.subscribers.forEach(e=>e.dispose()),this.subscribers.clear(),this.userAgentClients.forEach(e=>e.dispose()),this.userAgentClients.clear(),this.userAgentServers.forEach(e=>e.dispose()),this.userAgentServers.clear()}get loggerFactory(){return this.configuration.loggerFactory}get transport(){const e=this.configuration.transportAccessor();if(!e)throw new Error("Transport undefined.");return e}invite(e,t){return new ni(this,e,t)}message(e,t){return new gt(this,e,t)}publish(e,t){return new ai(this,e,t)}register(e,t){return new oi(this,e,t)}subscribe(e,t){return new li(this,e,t)}request(e,t){return new O(B,this,e,t)}makeOutgoingRequestMessage(e,t,i,s,r,n,o){const d=this.configuration.sipjsId,u=this.configuration.displayName,h=this.configuration.viaForceRport,m=this.configuration.hackViaTcp,S=this.configuration.supportedOptionTags.slice();e===v.REGISTER&&S.push("path","gruu"),e===v.INVITE&&(this.configuration.contact.pubGruu||this.configuration.contact.tempGruu)&&S.push("gruu");const x=this.configuration.routeSet,_=this.configuration.userAgentHeaderFieldValue,C=this.configuration.viaHost,p=Object.assign(Object.assign({},{callIdPrefix:d,forceRport:h,fromDisplayName:u,hackViaTcp:m,optionTags:S,routeSet:x,userAgentString:_,viaHost:C}),r);return new ge(e,t,i,s,p,n,o)}receiveIncomingRequestFromTransport(e){this.receiveRequestFromTransport(e)}receiveIncomingResponseFromTransport(e){this.receiveResponseFromTransport(e)}replyStateless(e,t){const i=this.configuration.userAgentHeaderFieldValue,s=this.configuration.supportedOptionTagsResponse;t=Object.assign(Object.assign({},t),{userAgent:i,supported:s});const r=lt(e,t);return this.transport.send(r.message).catch(n=>{n instanceof Error&&this.logger.error(n.message),this.logger.error(`Transport error occurred sending stateless reply to ${e.method} request.`)}),r}receiveRequestFromTransport(e){const t=e.viaBranch,i=this.userAgentServers.get(t);if(e.method===v.ACK&&i&&i.transaction.state===f.Accepted&&i instanceof Ve){this.logger.warn(`Discarding out of dialog ACK after 2xx response sent on transaction ${t}.`);return}if(e.method===v.CANCEL){i?(this.replyStateless(e,{statusCode:200}),i.transaction instanceof U&&i.transaction.state===f.Proceeding&&i instanceof Ve&&i.receiveCancel(e)):this.replyStateless(e,{statusCode:481});return}if(i){i.transaction.receiveRequest(e);return}this.receiveRequest(e)}receiveRequest(e){if(!ae.includes(e.method)){const s="Allow: "+ae.toString();this.replyStateless(e,{statusCode:405,extraHeaders:[s]});return}if(!e.ruri)throw new Error("Request-URI undefined.");if(e.ruri.scheme!=="sip"){this.replyStateless(e,{statusCode:416});return}const t=e.ruri,i=s=>!!s&&s.user===t.user;if(!i(this.configuration.aor)&&!(i(this.configuration.contact.uri)||i(this.configuration.contact.pubGruu)||i(this.configuration.contact.tempGruu))){this.logger.warn("Request-URI does not point to us."),e.method!==v.ACK&&this.replyStateless(e,{statusCode:404});return}if(e.method===v.INVITE&&!e.hasHeader("Contact")){this.replyStateless(e,{statusCode:400,reasonPhrase:"Missing Contact Header"});return}if(!e.toTag){const s=e.viaBranch;if(!this.userAgentServers.has(s)&&Array.from(this.userAgentServers.values()).some(n=>n.transaction.request.fromTag===e.fromTag&&n.transaction.request.callId===e.callId&&n.transaction.request.cseq===e.cseq)){this.replyStateless(e,{statusCode:482});return}}e.toTag?this.receiveInsideDialogRequest(e):this.receiveOutsideDialogRequest(e)}receiveInsideDialogRequest(e){if(e.method===v.NOTIFY){const s=e.parseHeader("Event");if(!s||!s.event){this.replyStateless(e,{statusCode:489});return}const r=e.callId+e.toTag+s.event,n=this.subscribers.get(r);if(n){const o=new Me(this,e);n.onNotify(o);return}}const t=e.callId+e.toTag+e.fromTag,i=this.dialogs.get(t);if(i){if(e.method===v.OPTIONS){const s="Allow: "+ae.toString(),r="Accept: "+wt.toString();this.replyStateless(e,{statusCode:200,extraHeaders:[s,r]});return}i.receiveRequest(e);return}e.method!==v.ACK&&this.replyStateless(e,{statusCode:481})}receiveOutsideDialogRequest(e){switch(e.method){case v.ACK:break;case v.BYE:this.replyStateless(e,{statusCode:481});break;case v.CANCEL:throw new Error(`Unexpected out of dialog request method ${e.method}.`);case v.INFO:this.replyStateless(e,{statusCode:405});break;case v.INVITE:{const t=new Ve(this,e);this.delegate.onInvite?this.delegate.onInvite(t):t.reject()}break;case v.MESSAGE:{const t=new ft(this,e);this.delegate.onMessage?this.delegate.onMessage(t):t.accept()}break;case v.NOTIFY:{const t=new Me(this,e);this.delegate.onNotify?this.delegate.onNotify(t):t.reject({statusCode:405})}break;case v.OPTIONS:{const t="Allow: "+ae.toString(),i="Accept: "+wt.toString();this.replyStateless(e,{statusCode:200,extraHeaders:[t,i]})}break;case v.REFER:{const t=new pt(this,e);this.delegate.onRefer?this.delegate.onRefer(t):t.reject({statusCode:405})}break;case v.REGISTER:{const t=new ci(this,e);this.delegate.onRegister?this.delegate.onRegister(t):t.reject({statusCode:405})}break;case v.SUBSCRIBE:{const t=new hi(this,e);this.delegate.onSubscribe?this.delegate.onSubscribe(t):t.reject({statusCode:480})}break;default:throw new Error(`Unexpected out of dialog request method ${e.method}.`)}}receiveResponseFromTransport(e){if(e.getHeaders("via").length>1){this.logger.warn("More than one Via header field present in the response, dropping");return}const t=e.viaBranch+e.method,i=this.userAgentClients.get(t);i?i.transaction.receiveResponse(e):this.logger.warn(`Discarding unmatched ${e.statusCode} response to ${e.method} ${t}.`)}}function gi(){return a=>!a.audio&&!a.video?Promise.resolve(new MediaStream):navigator.mediaDevices===void 0?Promise.reject(new Error("Media devices not available in insecure contexts.")):navigator.mediaDevices.getUserMedia.call(navigator.mediaDevices,a)}function fi(){return{bundlePolicy:"balanced",certificates:void 0,iceCandidatePoolSize:0,iceServers:[{urls:"stun:stun.l.google.com:19302"}],iceTransportPolicy:"all",rtcpMuxPolicy:"require"}}class F{constructor(e,t,i){e.debug("SessionDescriptionHandler.constructor"),this.logger=e,this.mediaStreamFactory=t,this.sessionDescriptionHandlerConfiguration=i,this._localMediaStream=new MediaStream,this._remoteMediaStream=new MediaStream,this._peerConnection=new RTCPeerConnection(i?.peerConnectionConfiguration),this.initPeerConnectionEventHandlers()}get localMediaStream(){return this._localMediaStream}get remoteMediaStream(){return this._remoteMediaStream}get dataChannel(){return this._dataChannel}get peerConnection(){return this._peerConnection}get peerConnectionDelegate(){return this._peerConnectionDelegate}set peerConnectionDelegate(e){this._peerConnectionDelegate=e}static dispatchAddTrackEvent(e,t){e.dispatchEvent(new MediaStreamTrackEvent("addtrack",{track:t}))}static dispatchRemoveTrackEvent(e,t){e.dispatchEvent(new MediaStreamTrackEvent("removetrack",{track:t}))}close(){this.logger.debug("SessionDescriptionHandler.close"),this._peerConnection!==void 0&&(this._peerConnection.getReceivers().forEach(e=>{e.track&&e.track.stop()}),this._peerConnection.getSenders().forEach(e=>{e.track&&e.track.stop()}),this._dataChannel&&this._dataChannel.close(),this._peerConnection.close(),this._peerConnection=void 0)}enableReceiverTracks(e){const t=this.peerConnection;if(!t)throw new Error("Peer connection closed.");t.getReceivers().forEach(i=>{i.track&&(i.track.enabled=e)})}enableSenderTracks(e){const t=this.peerConnection;if(!t)throw new Error("Peer connection closed.");t.getSenders().forEach(i=>{i.track&&(i.track.enabled=e)})}getDescription(e,t){var i,s;if(this.logger.debug("SessionDescriptionHandler.getDescription"),this._peerConnection===void 0)return Promise.reject(new Error("Peer connection closed."));this.onDataChannel=e?.onDataChannel;const r=(i=e?.offerOptions)===null||i===void 0?void 0:i.iceRestart,n=e?.iceGatheringTimeout===void 0?(s=this.sessionDescriptionHandlerConfiguration)===null||s===void 0?void 0:s.iceGatheringTimeout:e?.iceGatheringTimeout;return this.getLocalMediaStream(e).then(()=>this.updateDirection(e)).then(()=>this.createDataChannel(e)).then(()=>this.createLocalOfferOrAnswer(e)).then(o=>this.applyModifiers(o,t)).then(o=>this.setLocalSessionDescription(o)).then(()=>this.waitForIceGatheringComplete(r,n)).then(()=>this.getLocalSessionDescription()).then(o=>({body:o.sdp,contentType:"application/sdp"})).catch(o=>{throw this.logger.error("SessionDescriptionHandler.getDescription failed - "+o),o})}hasDescription(e){return this.logger.debug("SessionDescriptionHandler.hasDescription"),e==="application/sdp"}iceGatheringComplete(){this.logger.debug("SessionDescriptionHandler.iceGatheringComplete"),this.iceGatheringCompleteTimeoutId!==void 0&&(this.logger.debug("SessionDescriptionHandler.iceGatheringComplete - clearing timeout"),clearTimeout(this.iceGatheringCompleteTimeoutId),this.iceGatheringCompleteTimeoutId=void 0),this.iceGatheringCompletePromise!==void 0&&(this.logger.debug("SessionDescriptionHandler.iceGatheringComplete - resolving promise"),this.iceGatheringCompleteResolve&&this.iceGatheringCompleteResolve(),this.iceGatheringCompletePromise=void 0,this.iceGatheringCompleteResolve=void 0,this.iceGatheringCompleteReject=void 0)}sendDtmf(e,t){if(this.logger.debug("SessionDescriptionHandler.sendDtmf"),this._peerConnection===void 0)return this.logger.error("SessionDescriptionHandler.sendDtmf failed - peer connection closed"),!1;const i=this._peerConnection.getSenders();if(i.length===0)return this.logger.error("SessionDescriptionHandler.sendDtmf failed - no senders"),!1;const s=i[0].dtmf;if(!s)return this.logger.error("SessionDescriptionHandler.sendDtmf failed - no DTMF sender"),!1;const r=t?.duration,n=t?.interToneGap;try{s.insertDTMF(e,r,n)}catch(o){return this.logger.error(o.toString()),!1}return this.logger.log("SessionDescriptionHandler.sendDtmf sent via RTP: "+e.toString()),!0}setDescription(e,t,i){if(this.logger.debug("SessionDescriptionHandler.setDescription"),this._peerConnection===void 0)return Promise.reject(new Error("Peer connection closed."));this.onDataChannel=t?.onDataChannel;const s=this._peerConnection.signalingState==="have-local-offer"?"answer":"offer";return this.getLocalMediaStream(t).then(()=>this.applyModifiers({sdp:e,type:s},i)).then(r=>this.setRemoteSessionDescription(r)).catch(r=>{throw this.logger.error("SessionDescriptionHandler.setDescription failed - "+r),r})}applyModifiers(e,t){return this.logger.debug("SessionDescriptionHandler.applyModifiers"),!t||t.length===0?Promise.resolve(e):t.reduce((i,s)=>i.then(s),Promise.resolve(e)).then(i=>{if(this.logger.debug("SessionDescriptionHandler.applyModifiers - modified sdp"),!i.sdp||!i.type)throw new Error("Invalid SDP.");return{sdp:i.sdp,type:i.type}})}createDataChannel(e){if(this._peerConnection===void 0)return Promise.reject(new Error("Peer connection closed."));if(e?.dataChannel!==!0||this._dataChannel)return Promise.resolve();switch(this._peerConnection.signalingState){case"stable":this.logger.debug("SessionDescriptionHandler.createDataChannel - creating data channel");try{return this._dataChannel=this._peerConnection.createDataChannel(e?.dataChannelLabel||"",e?.dataChannelOptions),this.onDataChannel&&this.onDataChannel(this._dataChannel),Promise.resolve()}catch(t){return Promise.reject(t)}case"have-remote-offer":return Promise.resolve();default:return Promise.reject(new Error("Invalid signaling state "+this._peerConnection.signalingState))}}createLocalOfferOrAnswer(e){if(this._peerConnection===void 0)return Promise.reject(new Error("Peer connection closed."));switch(this._peerConnection.signalingState){case"stable":return this.logger.debug("SessionDescriptionHandler.createLocalOfferOrAnswer - creating SDP offer"),this._peerConnection.createOffer(e?.offerOptions);case"have-remote-offer":return this.logger.debug("SessionDescriptionHandler.createLocalOfferOrAnswer - creating SDP answer"),this._peerConnection.createAnswer(e?.answerOptions);default:return Promise.reject(new Error("Invalid signaling state "+this._peerConnection.signalingState))}}getLocalMediaStream(e){if(this.logger.debug("SessionDescriptionHandler.getLocalMediaStream"),this._peerConnection===void 0)return Promise.reject(new Error("Peer connection closed."));let t=Object.assign({},e?.constraints);if(this.localMediaStreamConstraints){if(t.audio=t.audio||this.localMediaStreamConstraints.audio,t.video=t.video||this.localMediaStreamConstraints.video,JSON.stringify(this.localMediaStreamConstraints.audio)===JSON.stringify(t.audio)&&JSON.stringify(this.localMediaStreamConstraints.video)===JSON.stringify(t.video))return Promise.resolve()}else t.audio===void 0&&t.video===void 0&&(t={audio:!0});return this.localMediaStreamConstraints=t,this.mediaStreamFactory(t,this,e).then(i=>this.setLocalMediaStream(i))}setLocalMediaStream(e){if(this.logger.debug("SessionDescriptionHandler.setLocalMediaStream"),!this._peerConnection)throw new Error("Peer connection undefined.");const t=this._peerConnection,i=this._localMediaStream,s=[],r=d=>{const u=d.kind;if(u!=="audio"&&u!=="video")throw new Error(`Unknown new track kind ${u}.`);const h=t.getSenders().find(m=>m.track&&m.track.kind===u);h?s.push(new Promise(m=>{this.logger.debug(`SessionDescriptionHandler.setLocalMediaStream - replacing sender ${u} track`),m()}).then(()=>h.replaceTrack(d).then(()=>{const m=i.getTracks().find(S=>S.kind===u);m&&(m.stop(),i.removeTrack(m),F.dispatchRemoveTrackEvent(i,m)),i.addTrack(d),F.dispatchAddTrackEvent(i,d)}).catch(m=>{throw this.logger.error(`SessionDescriptionHandler.setLocalMediaStream - failed to replace sender ${u} track`),m}))):s.push(new Promise(m=>{this.logger.debug(`SessionDescriptionHandler.setLocalMediaStream - adding sender ${u} track`),m()}).then(()=>{try{t.addTrack(d,i)}catch(m){throw this.logger.error(`SessionDescriptionHandler.setLocalMediaStream - failed to add sender ${u} track`),m}i.addTrack(d),F.dispatchAddTrackEvent(i,d)}))},n=e.getAudioTracks();n.length&&r(n[0]);const o=e.getVideoTracks();return o.length&&r(o[0]),s.reduce((d,u)=>d.then(()=>u),Promise.resolve())}getLocalSessionDescription(){if(this.logger.debug("SessionDescriptionHandler.getLocalSessionDescription"),this._peerConnection===void 0)return Promise.reject(new Error("Peer connection closed."));const e=this._peerConnection.localDescription;return e?Promise.resolve(e):Promise.reject(new Error("Failed to get local session description"))}setLocalSessionDescription(e){return this.logger.debug("SessionDescriptionHandler.setLocalSessionDescription"),this._peerConnection===void 0?Promise.reject(new Error("Peer connection closed.")):this._peerConnection.setLocalDescription(e)}setRemoteSessionDescription(e){if(this.logger.debug("SessionDescriptionHandler.setRemoteSessionDescription"),this._peerConnection===void 0)return Promise.reject(new Error("Peer connection closed."));const t=e.sdp;let i;switch(this._peerConnection.signalingState){case"stable":i="offer";break;case"have-local-offer":i="answer";break;default:return Promise.reject(new Error("Invalid signaling state "+this._peerConnection.signalingState))}return t?this._peerConnection.setRemoteDescription({sdp:t,type:i}):(this.logger.error("SessionDescriptionHandler.setRemoteSessionDescription failed - cannot set null sdp"),Promise.reject(new Error("SDP is undefined")))}setRemoteTrack(e){this.logger.debug("SessionDescriptionHandler.setRemoteTrack");const t=this._remoteMediaStream;t.getTrackById(e.id)?this.logger.debug(`SessionDescriptionHandler.setRemoteTrack - have remote ${e.kind} track`):e.kind==="audio"?(this.logger.debug(`SessionDescriptionHandler.setRemoteTrack - adding remote ${e.kind} track`),t.getAudioTracks().forEach(i=>{i.stop(),t.removeTrack(i),F.dispatchRemoveTrackEvent(t,i)}),t.addTrack(e),F.dispatchAddTrackEvent(t,e)):e.kind==="video"&&(this.logger.debug(`SessionDescriptionHandler.setRemoteTrack - adding remote ${e.kind} track`),t.getVideoTracks().forEach(i=>{i.stop(),t.removeTrack(i),F.dispatchRemoveTrackEvent(t,i)}),t.addTrack(e),F.dispatchAddTrackEvent(t,e))}updateDirection(e){if(this._peerConnection===void 0)return Promise.reject(new Error("Peer connection closed."));switch(this._peerConnection.signalingState){case"stable":this.logger.debug("SessionDescriptionHandler.updateDirection - setting offer direction");{const t=i=>{switch(i){case"inactive":return e?.hold?"inactive":"recvonly";case"recvonly":return e?.hold?"inactive":"recvonly";case"sendonly":return e?.hold?"sendonly":"sendrecv";case"sendrecv":return e?.hold?"sendonly":"sendrecv";case"stopped":return"stopped";default:throw new Error("Should never happen")}};this._peerConnection.getTransceivers().forEach(i=>{if(i.direction){const s=t(i.direction);i.direction!==s&&(i.direction=s)}})}break;case"have-remote-offer":this.logger.debug("SessionDescriptionHandler.updateDirection - setting answer direction");{const t=(()=>{const s=this._peerConnection.remoteDescription;if(!s)throw new Error("Failed to read remote offer");const r=/a=sendrecv\r\n|a=sendonly\r\n|a=recvonly\r\n|a=inactive\r\n/.exec(s.sdp);if(r)switch(r[0]){case`a=inactive\r
|
|
49
49
|
`:return"inactive";case`a=recvonly\r
|
|
50
50
|
`:return"recvonly";case`a=sendonly\r
|
|
51
51
|
`:return"sendonly";case`a=sendrecv\r
|
|
52
|
-
`:return"sendrecv";default:throw new Error("Should never happen")}return"sendrecv"})(),i=(()=>{switch(t){case"inactive":return"inactive";case"recvonly":return"sendonly";case"sendonly":return e?.hold?"inactive":"recvonly";case"sendrecv":return e?.hold?"sendonly":"sendrecv";default:throw new Error("Should never happen")}})();this._peerConnection.getTransceivers().forEach(s=>{s.direction&&s.direction!=="stopped"&&s.direction!==i&&(s.direction=i)})}break;default:return Promise.reject(new Error("Invalid signaling state "+this._peerConnection.signalingState))}return Promise.resolve()}waitForIceGatheringComplete(e=!1,t=0){return this.logger.debug("SessionDescriptionHandler.waitForIceGatheringToComplete"),this._peerConnection===void 0?Promise.reject("Peer connection closed."):!e&&this._peerConnection.iceGatheringState==="complete"?(this.logger.debug("SessionDescriptionHandler.waitForIceGatheringToComplete - already complete"),Promise.resolve()):(this.iceGatheringCompletePromise!==void 0&&(this.logger.debug("SessionDescriptionHandler.waitForIceGatheringToComplete - rejecting prior waiting promise"),this.iceGatheringCompleteReject&&this.iceGatheringCompleteReject(new Error("Promise superseded.")),this.iceGatheringCompletePromise=void 0,this.iceGatheringCompleteResolve=void 0,this.iceGatheringCompleteReject=void 0),this.iceGatheringCompletePromise=new Promise((i,s)=>{this.iceGatheringCompleteResolve=i,this.iceGatheringCompleteReject=s,t>0&&(this.logger.debug("SessionDescriptionHandler.waitForIceGatheringToComplete - timeout in "+t),this.iceGatheringCompleteTimeoutId=setTimeout(()=>{this.logger.debug("SessionDescriptionHandler.waitForIceGatheringToComplete - timeout"),this.iceGatheringComplete()},t))}),this.iceGatheringCompletePromise)}initPeerConnectionEventHandlers(){if(this.logger.debug("SessionDescriptionHandler.initPeerConnectionEventHandlers"),!this._peerConnection)throw new Error("Peer connection undefined.");const e=this._peerConnection;e.onconnectionstatechange=t=>{var i;const s=e.connectionState;this.logger.debug(`SessionDescriptionHandler.onconnectionstatechange ${s}`),!((i=this._peerConnectionDelegate)===null||i===void 0)&&i.onconnectionstatechange&&this._peerConnectionDelegate.onconnectionstatechange(t)},e.ondatachannel=t=>{var i;this.logger.debug("SessionDescriptionHandler.ondatachannel"),this._dataChannel=t.channel,this.onDataChannel&&this.onDataChannel(this._dataChannel),!((i=this._peerConnectionDelegate)===null||i===void 0)&&i.ondatachannel&&this._peerConnectionDelegate.ondatachannel(t)},e.onicecandidate=t=>{var i;this.logger.debug("SessionDescriptionHandler.onicecandidate"),!((i=this._peerConnectionDelegate)===null||i===void 0)&&i.onicecandidate&&this._peerConnectionDelegate.onicecandidate(t)},e.onicecandidateerror=t=>{var i;this.logger.debug("SessionDescriptionHandler.onicecandidateerror"),!((i=this._peerConnectionDelegate)===null||i===void 0)&&i.onicecandidateerror&&this._peerConnectionDelegate.onicecandidateerror(t)},e.oniceconnectionstatechange=t=>{var i;const s=e.iceConnectionState;this.logger.debug(`SessionDescriptionHandler.oniceconnectionstatechange ${s}`),!((i=this._peerConnectionDelegate)===null||i===void 0)&&i.oniceconnectionstatechange&&this._peerConnectionDelegate.oniceconnectionstatechange(t)},e.onicegatheringstatechange=t=>{var i;const s=e.iceGatheringState;this.logger.debug(`SessionDescriptionHandler.onicegatheringstatechange ${s}`),s==="complete"&&this.iceGatheringComplete(),!((i=this._peerConnectionDelegate)===null||i===void 0)&&i.onicegatheringstatechange&&this._peerConnectionDelegate.onicegatheringstatechange(t)},e.onnegotiationneeded=t=>{var i;this.logger.debug("SessionDescriptionHandler.onnegotiationneeded"),!((i=this._peerConnectionDelegate)===null||i===void 0)&&i.onnegotiationneeded&&this._peerConnectionDelegate.onnegotiationneeded(t)},e.onsignalingstatechange=t=>{var i;const s=e.signalingState;this.logger.debug(`SessionDescriptionHandler.onsignalingstatechange ${s}`),!((i=this._peerConnectionDelegate)===null||i===void 0)&&i.onsignalingstatechange&&this._peerConnectionDelegate.onsignalingstatechange(t)},e.ontrack=t=>{var i;const s=t.track.kind,r=t.track.enabled?"enabled":"disabled";this.logger.debug(`SessionDescriptionHandler.ontrack ${s} ${r}`),this.setRemoteTrack(t.track),!((i=this._peerConnectionDelegate)===null||i===void 0)&&i.ontrack&&this._peerConnectionDelegate.ontrack(t)}}}function
|
|
52
|
+
`:return"sendrecv";default:throw new Error("Should never happen")}return"sendrecv"})(),i=(()=>{switch(t){case"inactive":return"inactive";case"recvonly":return"sendonly";case"sendonly":return e?.hold?"inactive":"recvonly";case"sendrecv":return e?.hold?"sendonly":"sendrecv";default:throw new Error("Should never happen")}})();this._peerConnection.getTransceivers().forEach(s=>{s.direction&&s.direction!=="stopped"&&s.direction!==i&&(s.direction=i)})}break;default:return Promise.reject(new Error("Invalid signaling state "+this._peerConnection.signalingState))}return Promise.resolve()}waitForIceGatheringComplete(e=!1,t=0){return this.logger.debug("SessionDescriptionHandler.waitForIceGatheringToComplete"),this._peerConnection===void 0?Promise.reject("Peer connection closed."):!e&&this._peerConnection.iceGatheringState==="complete"?(this.logger.debug("SessionDescriptionHandler.waitForIceGatheringToComplete - already complete"),Promise.resolve()):(this.iceGatheringCompletePromise!==void 0&&(this.logger.debug("SessionDescriptionHandler.waitForIceGatheringToComplete - rejecting prior waiting promise"),this.iceGatheringCompleteReject&&this.iceGatheringCompleteReject(new Error("Promise superseded.")),this.iceGatheringCompletePromise=void 0,this.iceGatheringCompleteResolve=void 0,this.iceGatheringCompleteReject=void 0),this.iceGatheringCompletePromise=new Promise((i,s)=>{this.iceGatheringCompleteResolve=i,this.iceGatheringCompleteReject=s,t>0&&(this.logger.debug("SessionDescriptionHandler.waitForIceGatheringToComplete - timeout in "+t),this.iceGatheringCompleteTimeoutId=setTimeout(()=>{this.logger.debug("SessionDescriptionHandler.waitForIceGatheringToComplete - timeout"),this.iceGatheringComplete()},t))}),this.iceGatheringCompletePromise)}initPeerConnectionEventHandlers(){if(this.logger.debug("SessionDescriptionHandler.initPeerConnectionEventHandlers"),!this._peerConnection)throw new Error("Peer connection undefined.");const e=this._peerConnection;e.onconnectionstatechange=t=>{var i;const s=e.connectionState;this.logger.debug(`SessionDescriptionHandler.onconnectionstatechange ${s}`),!((i=this._peerConnectionDelegate)===null||i===void 0)&&i.onconnectionstatechange&&this._peerConnectionDelegate.onconnectionstatechange(t)},e.ondatachannel=t=>{var i;this.logger.debug("SessionDescriptionHandler.ondatachannel"),this._dataChannel=t.channel,this.onDataChannel&&this.onDataChannel(this._dataChannel),!((i=this._peerConnectionDelegate)===null||i===void 0)&&i.ondatachannel&&this._peerConnectionDelegate.ondatachannel(t)},e.onicecandidate=t=>{var i;this.logger.debug("SessionDescriptionHandler.onicecandidate"),!((i=this._peerConnectionDelegate)===null||i===void 0)&&i.onicecandidate&&this._peerConnectionDelegate.onicecandidate(t)},e.onicecandidateerror=t=>{var i;this.logger.debug("SessionDescriptionHandler.onicecandidateerror"),!((i=this._peerConnectionDelegate)===null||i===void 0)&&i.onicecandidateerror&&this._peerConnectionDelegate.onicecandidateerror(t)},e.oniceconnectionstatechange=t=>{var i;const s=e.iceConnectionState;this.logger.debug(`SessionDescriptionHandler.oniceconnectionstatechange ${s}`),!((i=this._peerConnectionDelegate)===null||i===void 0)&&i.oniceconnectionstatechange&&this._peerConnectionDelegate.oniceconnectionstatechange(t)},e.onicegatheringstatechange=t=>{var i;const s=e.iceGatheringState;this.logger.debug(`SessionDescriptionHandler.onicegatheringstatechange ${s}`),s==="complete"&&this.iceGatheringComplete(),!((i=this._peerConnectionDelegate)===null||i===void 0)&&i.onicegatheringstatechange&&this._peerConnectionDelegate.onicegatheringstatechange(t)},e.onnegotiationneeded=t=>{var i;this.logger.debug("SessionDescriptionHandler.onnegotiationneeded"),!((i=this._peerConnectionDelegate)===null||i===void 0)&&i.onnegotiationneeded&&this._peerConnectionDelegate.onnegotiationneeded(t)},e.onsignalingstatechange=t=>{var i;const s=e.signalingState;this.logger.debug(`SessionDescriptionHandler.onsignalingstatechange ${s}`),!((i=this._peerConnectionDelegate)===null||i===void 0)&&i.onsignalingstatechange&&this._peerConnectionDelegate.onsignalingstatechange(t)},e.ontrack=t=>{var i;const s=t.track.kind,r=t.track.enabled?"enabled":"disabled";this.logger.debug(`SessionDescriptionHandler.ontrack ${s} ${r}`),this.setRemoteTrack(t.track),!((i=this._peerConnectionDelegate)===null||i===void 0)&&i.ontrack&&this._peerConnectionDelegate.ontrack(t)}}}function pi(a){return(e,t)=>{a===void 0&&(a=gi());const s={iceGatheringTimeout:t?.iceGatheringTimeout!==void 0?t?.iceGatheringTimeout:5e3,peerConnectionConfiguration:Object.assign(Object.assign({},fi()),t?.peerConnectionConfiguration)},r=e.userAgent.getLogger("sip.SessionDescriptionHandler");return new F(r,a,s)}}class xe{constructor(e,t){if(this._state=T.Disconnected,this.transitioningState=!1,this._stateEventEmitter=new Te,this.logger=e,t){const r=t,n=r?.wsServers,o=r?.maxReconnectionAttempts;n!==void 0&&this.logger.warn('The transport option "wsServers" as has apparently been specified and has been deprecated. It will no longer be available starting with SIP.js release 0.16.0. Please update accordingly.'),o!==void 0&&this.logger.warn('The transport option "maxReconnectionAttempts" as has apparently been specified and has been deprecated. It will no longer be available starting with SIP.js release 0.16.0. Please update accordingly.'),n&&!t.server&&(typeof n=="string"&&(t.server=n),n instanceof Array&&(t.server=n[0]))}this.configuration=Object.assign(Object.assign({},xe.defaultOptions),t);const i=this.configuration.server,s=P.parse(i,"absoluteURI");if(s===-1)throw this.logger.error(`Invalid WebSocket Server URL "${i}"`),new Error("Invalid WebSocket Server URL");if(!["wss","ws","udp"].includes(s.scheme))throw this.logger.error(`Invalid scheme in WebSocket Server URL "${i}"`),new Error("Invalid scheme in WebSocket Server URL");this._protocol=s.scheme.toUpperCase()}dispose(){return this.disconnect()}get protocol(){return this._protocol}get server(){return this.configuration.server}get state(){return this._state}get stateChange(){return this._stateEventEmitter}get ws(){return this._ws}connect(){return this._connect()}disconnect(){return this._disconnect()}isConnected(){return this.state===T.Connected}send(e){return this._send(e)}_connect(){switch(this.logger.log(`Connecting ${this.server}`),this.state){case T.Connecting:if(this.transitioningState)return Promise.reject(this.transitionLoopDetectedError(T.Connecting));if(!this.connectPromise)throw new Error("Connect promise must be defined.");return this.connectPromise;case T.Connected:if(this.transitioningState)return Promise.reject(this.transitionLoopDetectedError(T.Connecting));if(this.connectPromise)throw new Error("Connect promise must not be defined.");return Promise.resolve();case T.Disconnecting:if(this.connectPromise)throw new Error("Connect promise must not be defined.");try{this.transitionState(T.Connecting)}catch(t){if(t instanceof Se)return Promise.reject(t);throw t}break;case T.Disconnected:if(this.connectPromise)throw new Error("Connect promise must not be defined.");try{this.transitionState(T.Connecting)}catch(t){if(t instanceof Se)return Promise.reject(t);throw t}break;default:throw new Error("Unknown state")}let e;try{e=new WebSocket(this.server,"sip"),e.binaryType="arraybuffer",e.addEventListener("close",t=>this.onWebSocketClose(t,e)),e.addEventListener("error",t=>this.onWebSocketError(t,e)),e.addEventListener("open",t=>this.onWebSocketOpen(t,e)),e.addEventListener("message",t=>this.onWebSocketMessage(t,e)),this._ws=e}catch(t){return this._ws=void 0,this.logger.error("WebSocket construction failed."),this.logger.error(t.toString()),new Promise((i,s)=>{this.connectResolve=i,this.connectReject=s,this.transitionState(T.Disconnected,t)})}return this.connectPromise=new Promise((t,i)=>{this.connectResolve=t,this.connectReject=i,this.connectTimeout=setTimeout(()=>{this.logger.warn("Connect timed out. Exceeded time set in configuration.connectionTimeout: "+this.configuration.connectionTimeout+"s."),e.close(1e3)},this.configuration.connectionTimeout*1e3)}),this.connectPromise}_disconnect(){switch(this.logger.log(`Disconnecting ${this.server}`),this.state){case T.Connecting:if(this.disconnectPromise)throw new Error("Disconnect promise must not be defined.");try{this.transitionState(T.Disconnecting)}catch(t){if(t instanceof Se)return Promise.reject(t);throw t}break;case T.Connected:if(this.disconnectPromise)throw new Error("Disconnect promise must not be defined.");try{this.transitionState(T.Disconnecting)}catch(t){if(t instanceof Se)return Promise.reject(t);throw t}break;case T.Disconnecting:if(this.transitioningState)return Promise.reject(this.transitionLoopDetectedError(T.Disconnecting));if(!this.disconnectPromise)throw new Error("Disconnect promise must be defined.");return this.disconnectPromise;case T.Disconnected:if(this.transitioningState)return Promise.reject(this.transitionLoopDetectedError(T.Disconnecting));if(this.disconnectPromise)throw new Error("Disconnect promise must not be defined.");return Promise.resolve();default:throw new Error("Unknown state")}if(!this._ws)throw new Error("WebSocket must be defined.");const e=this._ws;return this.disconnectPromise=new Promise((t,i)=>{this.disconnectResolve=t,this.disconnectReject=i;try{e.close(1e3)}catch(s){throw this.logger.error("WebSocket close failed."),this.logger.error(s.toString()),s}}),this.disconnectPromise}_send(e){if(this.configuration.traceSip===!0&&this.logger.log(`Sending WebSocket message:
|
|
53
53
|
|
|
54
54
|
`+e+`
|
|
55
55
|
`),this._state!==T.Connected)return Promise.reject(new Error("Not connected."));if(!this._ws)throw new Error("WebSocket undefined.");try{this._ws.send(e)}catch(t){return t instanceof Error?Promise.reject(t):Promise.reject(new Error("WebSocket send failed."))}return Promise.resolve()}onWebSocketClose(e,t){if(t!==this._ws)return;const i=`WebSocket closed ${this.server} (code: ${e.code})`,s=this.disconnectPromise?void 0:new Error(i);s&&this.logger.warn("WebSocket closed unexpectedly"),this.logger.log(i),this._ws=void 0,this.transitionState(T.Disconnected,s)}onWebSocketError(e,t){t===this._ws&&this.logger.error("WebSocket error occurred.")}onWebSocketMessage(e,t){if(t!==this._ws)return;const i=e.data;let s;if(/^(\r\n)+$/.test(i)){this.clearKeepAliveTimeout(),this.configuration.traceSip===!0&&this.logger.log("Received WebSocket message with CRLF Keep Alive response");return}if(!i){this.logger.warn("Received empty message, discarding...");return}if(typeof i!="string"){try{s=new TextDecoder().decode(new Uint8Array(i))}catch(r){this.logger.error(r.toString()),this.logger.error("Received WebSocket binary message failed to be converted into string, message discarded");return}this.configuration.traceSip===!0&&this.logger.log(`Received WebSocket binary message:
|
|
@@ -58,66 +58,264 @@ var EmbeddedCallWidgetRuntimeBundle=(function(Fe){"use strict";const Dt="0.21.1"
|
|
|
58
58
|
`)}else s=i,this.configuration.traceSip===!0&&this.logger.log(`Received WebSocket text message:
|
|
59
59
|
|
|
60
60
|
`+s+`
|
|
61
|
-
`);if(this.state!==T.Connected){this.logger.warn("Received message while not connected, discarding...");return}if(this.onMessage)try{this.onMessage(s)}catch(r){throw this.logger.error(r.toString()),this.logger.error("Exception thrown by onMessage callback"),r}}onWebSocketOpen(e,t){t===this._ws&&this._state===T.Connecting&&(this.logger.log(`WebSocket opened ${this.server}`),this.transitionState(T.Connected))}transitionLoopDetectedError(e){let t="A state transition loop has been detected.";return t+=` An attempt to transition from ${this._state} to ${e} before the prior transition completed.`,t+=" Perhaps you are synchronously calling connect() or disconnect() from a callback or state change handler?",this.logger.error(t),new
|
|
61
|
+
`);if(this.state!==T.Connected){this.logger.warn("Received message while not connected, discarding...");return}if(this.onMessage)try{this.onMessage(s)}catch(r){throw this.logger.error(r.toString()),this.logger.error("Exception thrown by onMessage callback"),r}}onWebSocketOpen(e,t){t===this._ws&&this._state===T.Connecting&&(this.logger.log(`WebSocket opened ${this.server}`),this.transitionState(T.Connected))}transitionLoopDetectedError(e){let t="A state transition loop has been detected.";return t+=` An attempt to transition from ${this._state} to ${e} before the prior transition completed.`,t+=" Perhaps you are synchronously calling connect() or disconnect() from a callback or state change handler?",this.logger.error(t),new Se("Loop detected.")}transitionState(e,t){const i=()=>{throw new Error(`Invalid state transition from ${this._state} to ${e}`)};if(this.transitioningState)throw this.transitionLoopDetectedError(e);switch(this.transitioningState=!0,this._state){case T.Connecting:e!==T.Connected&&e!==T.Disconnecting&&e!==T.Disconnected&&i();break;case T.Connected:e!==T.Disconnecting&&e!==T.Disconnected&&i();break;case T.Disconnecting:e!==T.Connecting&&e!==T.Disconnected&&i();break;case T.Disconnected:e!==T.Connecting&&i();break;default:throw new Error("Unknown state.")}const s=this._state;this._state=e;const r=this.connectResolve,n=this.connectReject;s===T.Connecting&&(this.connectPromise=void 0,this.connectResolve=void 0,this.connectReject=void 0);const o=this.disconnectResolve,d=this.disconnectReject;if(s===T.Disconnecting&&(this.disconnectPromise=void 0,this.disconnectResolve=void 0,this.disconnectReject=void 0),this.connectTimeout&&(clearTimeout(this.connectTimeout),this.connectTimeout=void 0),this.logger.log(`Transitioned from ${s} to ${this._state}`),this._stateEventEmitter.emit(this._state),e===T.Connected&&(this.startSendingKeepAlives(),this.onConnect))try{this.onConnect()}catch(u){throw this.logger.error(u.toString()),this.logger.error("Exception thrown by onConnect callback"),u}if(s===T.Connected&&(this.stopSendingKeepAlives(),this.onDisconnect))try{t?this.onDisconnect(t):this.onDisconnect()}catch(u){throw this.logger.error(u.toString()),this.logger.error("Exception thrown by onDisconnect callback"),u}if(s===T.Connecting){if(!r)throw new Error("Connect resolve undefined.");if(!n)throw new Error("Connect reject undefined.");e===T.Connected?r():n(t||new Error("Connect aborted."))}if(s===T.Disconnecting){if(!o)throw new Error("Disconnect resolve undefined.");if(!d)throw new Error("Disconnect reject undefined.");e===T.Disconnected?o():d(t||new Error("Disconnect aborted."))}this.transitioningState=!1}clearKeepAliveTimeout(){this.keepAliveDebounceTimeout&&clearTimeout(this.keepAliveDebounceTimeout),this.keepAliveDebounceTimeout=void 0}sendKeepAlive(){return this.keepAliveDebounceTimeout?Promise.resolve():(this.keepAliveDebounceTimeout=setTimeout(()=>{this.clearKeepAliveTimeout()},this.configuration.keepAliveDebounce*1e3),this.send(`\r
|
|
62
62
|
\r
|
|
63
|
-
`))}startSendingKeepAlives(){const e=t=>{const i=t*.8;return 1e3*(Math.random()*(t-i)+i)};this.configuration.keepAliveInterval&&!this.keepAliveInterval&&(this.keepAliveInterval=setInterval(()=>{this.sendKeepAlive(),this.startSendingKeepAlives()},e(this.configuration.keepAliveInterval)))}stopSendingKeepAlives(){this.keepAliveInterval&&clearInterval(this.keepAliveInterval),this.keepAliveDebounceTimeout&&clearTimeout(this.keepAliveDebounceTimeout),this.keepAliveInterval=void 0,this.keepAliveDebounceTimeout=void 0}}Ee.defaultOptions={server:"",connectionTimeout:5,keepAliveInterval:0,keepAliveDebounce:10,traceSip:!0};class K{constructor(e={}){if(this._publishers={},this._registerers={},this._sessions={},this._subscriptions={},this._state=P.Stopped,this._stateEventEmitter=new Se,this.delegate=e.delegate,this.options=Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},K.defaultOptions()),{sipjsId:le(5)}),{uri:new z("sip","anonymous."+le(6),"anonymous.invalid")}),{viaHost:le(12)+".invalid"}),K.stripUndefinedProperties(e)),this.options.hackIpInContact)if(typeof this.options.hackIpInContact=="boolean"&&this.options.hackIpInContact){const s=Math.floor(Math.random()*254+1);this.options.viaHost="192.0.2."+s}else this.options.hackIpInContact&&(this.options.viaHost=this.options.hackIpInContact);switch(this.loggerFactory=new Gt,this.logger=this.loggerFactory.getLogger("sip.UserAgent"),this.loggerFactory.builtinEnabled=this.options.logBuiltinEnabled,this.loggerFactory.connector=this.options.logConnector,this.options.logLevel){case"error":this.loggerFactory.level=q.error;break;case"warn":this.loggerFactory.level=q.warn;break;case"log":this.loggerFactory.level=q.log;break;case"debug":this.loggerFactory.level=q.debug;break}if(this.options.logConfiguration&&(this.logger.log("Configuration:"),Object.keys(this.options).forEach(t=>{const i=this.options[t];switch(t){case"uri":case"sessionDescriptionHandlerFactory":this.logger.log("· "+t+": "+i);break;case"authorizationPassword":this.logger.log("· "+t+": NOT SHOWN");break;case"transportConstructor":this.logger.log("· "+t+": "+i.name);break;default:this.logger.log("· "+t+": "+JSON.stringify(i))}})),this.options.transportOptions){const t=this.options.transportOptions,i=t.maxReconnectionAttempts,s=t.reconnectionTimeout;i!==void 0&&this.logger.warn('The transport option "maxReconnectionAttempts" as has apparently been specified and has been deprecated. It will no longer be available starting with SIP.js release 0.16.0. Please update accordingly.'),s!==void 0&&this.logger.warn('The transport option "reconnectionTimeout" as has apparently been specified and has been deprecated. It will no longer be available starting with SIP.js release 0.16.0. Please update accordingly.'),e.reconnectionDelay===void 0&&s!==void 0&&(this.options.reconnectionDelay=s),e.reconnectionAttempts===void 0&&i!==void 0&&(this.options.reconnectionAttempts=i)}if(e.reconnectionDelay!==void 0&&this.logger.warn('The user agent option "reconnectionDelay" as has apparently been specified and has been deprecated. It will no longer be available starting with SIP.js release 0.16.0. Please update accordingly.'),e.reconnectionAttempts!==void 0&&this.logger.warn('The user agent option "reconnectionAttempts" as has apparently been specified and has been deprecated. It will no longer be available starting with SIP.js release 0.16.0. Please update accordingly.'),this._transport=new this.options.transportConstructor(this.getLogger("sip.Transport"),this.options.transportOptions),this.initTransportCallbacks(),this._contact=this.initContact(),this._instanceId=this.options.instanceId?this.options.instanceId:K.newUUID(),k.parse(this._instanceId,"uuid")===-1)throw new Error("Invalid instanceId.");this._userAgentCore=this.initCore()}static makeURI(e){return k.URIParse(e)}static defaultOptions(){return{allowLegacyNotifications:!1,authorizationHa1:"",authorizationPassword:"",authorizationUsername:"",delegate:{},contactName:"",contactParams:{transport:"ws"},displayName:"",forceRport:!1,gracefulShutdown:!0,hackAllowUnregisteredOptionTags:!1,hackIpInContact:!1,hackViaTcp:!1,instanceId:"",instanceIdAlwaysAdded:!1,logBuiltinEnabled:!0,logConfiguration:!0,logConnector:()=>{},logLevel:"log",noAnswerTimeout:60,preloadedRouteSet:[],reconnectionAttempts:0,reconnectionDelay:4,sendInitialProvisionalResponse:!0,sessionDescriptionHandlerFactory:fi(),sessionDescriptionHandlerFactoryOptions:{},sipExtension100rel:W.Unsupported,sipExtensionReplaces:W.Unsupported,sipExtensionExtraSupported:[],sipjsId:"",transportConstructor:Ee,transportOptions:{},uri:new z("sip","anonymous","anonymous.invalid"),userAgentString:"SIP.js/"+Dt,viaHost:""}}static newUUID(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{const i=Math.floor(Math.random()*16);return(t==="x"?i:i%4+8).toString(16)})}static stripUndefinedProperties(e){return Object.keys(e).reduce((t,i)=>(e[i]!==void 0&&(t[i]=e[i]),t),{})}get configuration(){return this.options}get contact(){return this._contact}get instanceId(){return this._instanceId}get state(){return this._state}get stateChange(){return this._stateEventEmitter}get transport(){return this._transport}get userAgentCore(){return this._userAgentCore}getLogger(e,t){return this.loggerFactory.getLogger(e,t)}getLoggerFactory(){return this.loggerFactory}isConnected(){return this.transport.isConnected()}reconnect(){return this.state===P.Stopped?Promise.reject(new Error("User agent stopped.")):Promise.resolve().then(()=>this.transport.connect())}start(){return this.state===P.Started?(this.logger.warn("User agent already started"),Promise.resolve()):(this.logger.log(`Starting ${this.configuration.uri}`),this.transitionState(P.Started),this.transport.connect())}async stop(){if(this.state===P.Stopped)return this.logger.warn("User agent already stopped"),Promise.resolve();if(this.logger.log(`Stopping ${this.configuration.uri}`),!this.options.gracefulShutdown)return this.logger.log("Dispose of transport"),this.transport.dispose().catch(a=>{throw this.logger.error(a.message),a}),this.logger.log("Dispose of core"),this.userAgentCore.dispose(),this._publishers={},this._registerers={},this._sessions={},this._subscriptions={},this.transitionState(P.Stopped),Promise.resolve();const e=Object.assign({},this._publishers),t=Object.assign({},this._registerers),i=Object.assign({},this._sessions),s=Object.assign({},this._subscriptions),r=this.transport,n=this.userAgentCore;this.logger.log("Dispose of registerers");for(const a in t)t[a]&&await t[a].dispose().catch(d=>{throw this.logger.error(d.message),delete this._registerers[a],d});this.logger.log("Dispose of sessions");for(const a in i)i[a]&&await i[a].dispose().catch(d=>{throw this.logger.error(d.message),delete this._sessions[a],d});this.logger.log("Dispose of subscriptions");for(const a in s)s[a]&&await s[a].dispose().catch(d=>{throw this.logger.error(d.message),delete this._subscriptions[a],d});this.logger.log("Dispose of publishers");for(const a in e)e[a]&&await e[a].dispose().catch(d=>{throw this.logger.error(d.message),delete this._publishers[a],d});this.logger.log("Dispose of transport"),await r.dispose().catch(a=>{throw this.logger.error(a.message),a}),this.logger.log("Dispose of core"),n.dispose(),this.transitionState(P.Stopped)}_makeInviter(e,t){return new De(this,e,t)}attemptReconnection(e=1){const t=this.options.reconnectionAttempts,i=this.options.reconnectionDelay;if(e>t){this.logger.log("Maximum reconnection attempts reached");return}this.logger.log(`Reconnection attempt ${e} of ${t} - trying`),setTimeout(()=>{this.reconnect().then(()=>{this.logger.log(`Reconnection attempt ${e} of ${t} - succeeded`)}).catch(s=>{this.logger.error(s.message),this.logger.log(`Reconnection attempt ${e} of ${t} - failed`),this.attemptReconnection(++e)})},e===1?0:i*1e3)}initContact(){const e=this.options.contactName!==""?this.options.contactName:le(8),t=this.options.contactParams;return{pubGruu:void 0,tempGruu:void 0,uri:new z("sip",e,this.options.viaHost,void 0,t),toString:(s={})=>{const r=s.anonymous||!1,n=s.outbound||!1,a=s.register||!1;let d="<";return r?d+=this.contact.tempGruu||`sip:anonymous@anonymous.invalid;transport=${t.transport?t.transport:"ws"}`:a?d+=this.contact.uri:d+=this.contact.pubGruu||this.contact.uri,n&&(d+=";ob"),d+=">",this.options.instanceIdAlwaysAdded&&(d+=';+sip.instance="<urn:uuid:'+this._instanceId+'>"'),d}}}initCore(){let e=[];e.push("outbound"),this.options.sipExtension100rel===W.Supported&&e.push("100rel"),this.options.sipExtensionReplaces===W.Supported&&e.push("replaces"),this.options.sipExtensionExtraSupported&&e.push(...this.options.sipExtensionExtraSupported),this.options.hackAllowUnregisteredOptionTags||(e=e.filter(r=>Bt[r])),e=Array.from(new Set(e));const t=e.slice();(this.contact.pubGruu||this.contact.tempGruu)&&t.push("gruu");const i={aor:this.options.uri,contact:this.contact,displayName:this.options.displayName,loggerFactory:this.loggerFactory,hackViaTcp:this.options.hackViaTcp,routeSet:this.options.preloadedRouteSet,supportedOptionTags:e,supportedOptionTagsResponse:t,sipjsId:this.options.sipjsId,userAgentHeaderFieldValue:this.options.userAgentString,viaForceRport:this.options.forceRport,viaHost:this.options.viaHost,authenticationFactory:()=>{const r=this.options.authorizationUsername?this.options.authorizationUsername:this.options.uri.user,n=this.options.authorizationPassword?this.options.authorizationPassword:void 0,a=this.options.authorizationHa1?this.options.authorizationHa1:void 0;return new Vt(this.getLoggerFactory(),a,r,n)},transportAccessor:()=>this.transport},s={onInvite:r=>{var n;const a=new ue(this,r);if(r.delegate={onCancel:d=>{a._onCancel(d)},onTransportError:d=>{this.logger.error("A transport error has occurred while handling an incoming INVITE request.")}},r.trying(),this.options.sipExtensionReplaces!==W.Unsupported){const f=r.message.parseHeader("replaces");if(f){const h=f.call_id;if(typeof h!="string")throw new Error("Type of call id is not string");const w=f.replaces_to_tag;if(typeof w!="string")throw new Error("Type of to tag is not string");const S=f.replaces_from_tag;if(typeof S!="string")throw new Error("type of from tag is not string");const x=h+w+S,I=this.userAgentCore.dialogs.get(x);if(!I){a.reject({statusCode:481});return}if(!I.early&&f.early_only===!0){a.reject({statusCode:486});return}const E=this._sessions[h+S]||this._sessions[h+w]||void 0;if(!E)throw new Error("Session does not exist.");a._replacee=E}}if(!((n=this.delegate)===null||n===void 0)&&n.onInvite){if(a.autoSendAnInitialProvisionalResponse){a.progress().then(()=>{var d;if(((d=this.delegate)===null||d===void 0?void 0:d.onInvite)===void 0)throw new Error("onInvite undefined.");this.delegate.onInvite(a)});return}this.delegate.onInvite(a);return}a.reject({statusCode:486})},onMessage:r=>{if(this.delegate&&this.delegate.onMessage){const n=new at(r);this.delegate.onMessage(n)}else r.accept()},onNotify:r=>{if(this.delegate&&this.delegate.onNotify){const n=new Be(r);this.delegate.onNotify(n)}else this.options.allowLegacyNotifications?r.accept():r.reject({statusCode:481})},onRefer:r=>{this.logger.warn("Received an out of dialog REFER request"),this.delegate&&this.delegate.onReferRequest?this.delegate.onReferRequest(r):r.reject({statusCode:405})},onRegister:r=>{this.logger.warn("Received an out of dialog REGISTER request"),this.delegate&&this.delegate.onRegisterRequest?this.delegate.onRegisterRequest(r):r.reject({statusCode:405})},onSubscribe:r=>{this.logger.warn("Received an out of dialog SUBSCRIBE request"),this.delegate&&this.delegate.onSubscribeRequest?this.delegate.onSubscribeRequest(r):r.reject({statusCode:405})}};return new hi(i,s)}initTransportCallbacks(){this.transport.onConnect=()=>this.onTransportConnect(),this.transport.onDisconnect=e=>this.onTransportDisconnect(e),this.transport.onMessage=e=>this.onTransportMessage(e)}onTransportConnect(){this.state!==P.Stopped&&this.delegate&&this.delegate.onConnect&&this.delegate.onConnect()}onTransportDisconnect(e){this.state!==P.Stopped&&(this.delegate&&this.delegate.onDisconnect&&this.delegate.onDisconnect(e),e&&this.options.reconnectionAttempts>0&&this.attemptReconnection())}onTransportMessage(e){const t=ke.parseMessage(e,this.getLogger("sip.Parser"));if(!t){this.logger.warn("Failed to parse incoming message. Dropping.");return}if(this.state===P.Stopped&&t instanceof pe){this.logger.warn(`Received ${t.method} request while stopped. Dropping.`);return}const i=()=>{const s=["from","to","call_id","cseq","via"];for(const r of s)if(!t.hasHeader(r))return this.logger.warn(`Missing mandatory header field : ${r}.`),!1;return!0};if(t instanceof pe){if(!i()){this.logger.warn("Request missing mandatory header field. Dropping.");return}if(!t.toTag&&t.callId.substr(0,5)===this.options.sipjsId){this.userAgentCore.replyStateless(t,{statusCode:482});return}const s=Te(t.body),r=t.getHeader("content-length");if(r&&s<Number(r)){this.userAgentCore.replyStateless(t,{statusCode:400});return}}if(t instanceof se){if(!i()){this.logger.warn("Response missing mandatory header field. Dropping.");return}if(t.getHeaders("via").length>1){this.logger.warn("More than one Via header field present in the response. Dropping.");return}if(t.via.host!==this.options.viaHost||t.via.port!==void 0){this.logger.warn("Via sent-by in the response does not match UA Via host value. Dropping.");return}const s=Te(t.body),r=t.getHeader("content-length");if(r&&s<Number(r)){this.logger.warn("Message body length is lower than the value in Content-Length header field. Dropping.");return}}if(t instanceof pe){this.userAgentCore.receiveIncomingRequestFromTransport(t);return}if(t instanceof se){this.userAgentCore.receiveIncomingResponseFromTransport(t);return}throw new Error("Invalid message type.")}transitionState(e,t){const i=()=>{throw new Error(`Invalid state transition from ${this._state} to ${e}`)};switch(this._state){case P.Started:e!==P.Stopped&&i();break;case P.Stopped:e!==P.Started&&i();break;default:throw new Error("Unknown state.")}this.logger.log(`Transitioned from ${this._state} to ${e}`),this._state=e,this._stateEventEmitter.emit(this._state)}}function pi(){return(o,e)=>({session:e,held:!1,muted:!1})}class Ge{constructor(e,t={}){this.managedSessions=[],this.attemptingReconnection=!1,this.optionsPingFailure=!1,this.optionsPingRunning=!1,this.shouldBeConnected=!1,this.shouldBeRegistered=!1,this.delegate=t.delegate,this.options=Object.assign({aor:"",autoStop:!0,delegate:{},iceStopWaitingOnServerReflexive:!1,managedSessionFactory:pi(),maxSimultaneousSessions:2,media:{},optionsPingInterval:-1,optionsPingRequestURI:"",reconnectionAttempts:3,reconnectionDelay:4,registrationRetry:!1,registrationRetryInterval:3,registerGuard:null,registererOptions:{},registererRegisterOptions:{},sendDTMFUsingSessionDescriptionHandler:!1,userAgentOptions:{}},Ge.stripUndefinedProperties(t));const i=Object.assign({},t.userAgentOptions);if(i.transportConstructor||(i.transportConstructor=Ee),i.transportOptions||(i.transportOptions={server:e}),!i.uri&&t.aor){const s=K.makeURI(t.aor);if(!s)throw new Error(`Failed to create valid URI from ${t.aor}`);i.uri=s}if(this.userAgent=new K(i),this.userAgent.delegate={onConnect:()=>{this.logger.log("Connected"),this.delegate&&this.delegate.onServerConnect&&this.delegate.onServerConnect(),this.shouldBeRegistered&&this.register(),this.options.optionsPingInterval>0&&this.optionsPingStart()},onDisconnect:async s=>{this.logger.log("Disconnected");let r=!1;this.options.optionsPingInterval>0&&(r=this.optionsPingFailure,this.optionsPingFailure=!1,this.optionsPingStop()),this.delegate&&this.delegate.onServerDisconnect&&this.delegate.onServerDisconnect(s),(s||r)&&(this.registerer&&(this.logger.log("Disposing of registerer..."),this.registerer.dispose().catch(n=>{this.logger.debug("Error occurred disposing of registerer after connection with server was lost."),this.logger.debug(n.toString())}),this.registerer=void 0),this.managedSessions.slice().map(n=>n.session).forEach(async n=>{this.logger.log("Disposing of session..."),n.dispose().catch(a=>{this.logger.debug("Error occurred disposing of a session after connection with server was lost."),this.logger.debug(a.toString())})}),this.shouldBeConnected&&this.attemptReconnection())},onInvite:s=>{this.logger.log(`[${s.id}] Received INVITE`);const r=this.options.maxSimultaneousSessions;if(r!==0&&this.managedSessions.length>r){this.logger.warn(`[${s.id}] Session already in progress, rejecting INVITE...`),s.reject().then(()=>{this.logger.log(`[${s.id}] Rejected INVITE`)}).catch(a=>{this.logger.error(`[${s.id}] Failed to reject INVITE`),this.logger.error(a.toString())});return}const n={sessionDescriptionHandlerOptions:{constraints:this.constraints}};this.initSession(s,n),this.delegate&&this.delegate.onCallReceived?this.delegate.onCallReceived(s):(this.logger.warn(`[${s.id}] No handler available, rejecting INVITE...`),s.reject().then(()=>{this.logger.log(`[${s.id}] Rejected INVITE`)}).catch(a=>{this.logger.error(`[${s.id}] Failed to reject INVITE`),this.logger.error(a.toString())}))},onMessage:s=>{s.accept().then(()=>{this.delegate&&this.delegate.onMessageReceived&&this.delegate.onMessageReceived(s)})},onNotify:s=>{s.accept().then(()=>{this.delegate&&this.delegate.onNotificationReceived&&this.delegate.onNotificationReceived(s)})}},this.registererOptions=Object.assign({},t.registererOptions),this.registererRegisterOptions=Object.assign({},t.registererRegisterOptions),this.options.registrationRetry){this.registererRegisterOptions.requestDelegate=this.registererRegisterOptions.requestDelegate||{};const s=this.registererRegisterOptions.requestDelegate.onReject;this.registererRegisterOptions.requestDelegate.onReject=r=>{s&&s(r),this.attemptRegistration()}}this.logger=this.userAgent.getLogger("sip.SessionManager"),window.addEventListener("online",()=>{this.logger.log("Online"),this.shouldBeConnected&&this.connect()}),this.options.autoStop&&window.addEventListener("beforeunload",async()=>{this.shouldBeConnected=!1,this.shouldBeRegistered=!1,this.userAgent.state!==P.Stopped&&await this.userAgent.stop()})}static stripUndefinedProperties(e){return Object.keys(e).reduce((t,i)=>(e[i]!==void 0&&(t[i]=e[i]),t),{})}getLocalMediaStream(e){const t=e.sessionDescriptionHandler;if(t){if(!(t instanceof F))throw new Error("Session description handler not instance of web SessionDescriptionHandler");return t.localMediaStream}}getRemoteMediaStream(e){const t=e.sessionDescriptionHandler;if(t){if(!(t instanceof F))throw new Error("Session description handler not instance of web SessionDescriptionHandler");return t.remoteMediaStream}}getLocalAudioTrack(e){var t;return(t=this.getLocalMediaStream(e))===null||t===void 0?void 0:t.getTracks().find(i=>i.kind==="audio")}getLocalVideoTrack(e){var t;return(t=this.getLocalMediaStream(e))===null||t===void 0?void 0:t.getTracks().find(i=>i.kind==="video")}getRemoteAudioTrack(e){var t;return(t=this.getRemoteMediaStream(e))===null||t===void 0?void 0:t.getTracks().find(i=>i.kind==="audio")}getRemoteVideoTrack(e){var t;return(t=this.getRemoteMediaStream(e))===null||t===void 0?void 0:t.getTracks().find(i=>i.kind==="video")}async connect(){return this.logger.log("Connecting UserAgent..."),this.shouldBeConnected=!0,this.userAgent.state!==P.Started?this.userAgent.start():this.userAgent.reconnect()}async disconnect(){return this.logger.log("Disconnecting UserAgent..."),this.userAgent.state===P.Stopped?Promise.resolve():(this.shouldBeConnected=!1,this.shouldBeRegistered=!1,this.registerer=void 0,this.userAgent.stop())}isConnected(){return this.userAgent.isConnected()}async register(e){return this.logger.log("Registering UserAgent..."),this.shouldBeRegistered=!0,e!==void 0&&(this.registererRegisterOptions=Object.assign({},e)),this.registerer||(this.registerer=new J(this.userAgent,this.registererOptions),this.registerer.stateChange.addListener(t=>{switch(t){case _.Initial:break;case _.Registered:this.delegate&&this.delegate.onRegistered&&this.delegate.onRegistered();break;case _.Unregistered:this.delegate&&this.delegate.onUnregistered&&this.delegate.onUnregistered(),this.shouldBeRegistered&&this.attemptRegistration();break;case _.Terminated:break;default:throw new Error("Unknown registerer state.")}})),this.attemptRegistration(!0)}async unregister(e){return this.logger.log("Unregistering UserAgent..."),this.shouldBeRegistered=!1,this.registerer?this.registerer.unregister(e).then(()=>{}):(this.logger.warn("No registerer to unregister."),Promise.resolve())}async call(e,t,i){this.logger.log("Beginning Session...");const s=this.options.maxSimultaneousSessions;if(s!==0&&this.managedSessions.length>s)return Promise.reject(new Error("Maximum number of sessions already exists."));const r=K.makeURI(e);if(!r)return Promise.reject(new Error(`Failed to create a valid URI from "${e}"`));if(t||(t={}),t.sessionDescriptionHandlerOptions||(t.sessionDescriptionHandlerOptions={}),t.sessionDescriptionHandlerOptions.constraints||(t.sessionDescriptionHandlerOptions.constraints=this.constraints),t.earlyMedia){i=i||{},i.requestDelegate=i.requestDelegate||{};const a=i.requestDelegate.onProgress;i.requestDelegate.onProgress=d=>{d.message.statusCode===183&&this.setupRemoteMedia(n),a&&a(d)}}this.options.iceStopWaitingOnServerReflexive&&(t.delegate=t.delegate||{},t.delegate.onSessionDescriptionHandler=a=>{if(!(a instanceof F))throw new Error("Session description handler not instance of SessionDescriptionHandler");a.peerConnectionDelegate={onicecandidate:d=>{var f;((f=d.candidate)===null||f===void 0?void 0:f.type)==="srflx"&&(this.logger.log(`[${n.id}] Found srflx ICE candidate, stop waiting...`),a.iceGatheringComplete())}}});const n=new De(this.userAgent,r,t);return this.sendInvite(n,t,i).then(()=>n)}async hangup(e){return this.logger.log(`[${e.id}] Hangup...`),this.sessionExists(e)?this.terminate(e):Promise.reject(new Error("Session does not exist."))}async answer(e,t){return this.logger.log(`[${e.id}] Accepting Invitation...`),this.sessionExists(e)?e instanceof ue?(t||(t={}),t.sessionDescriptionHandlerOptions||(t.sessionDescriptionHandlerOptions={}),t.sessionDescriptionHandlerOptions.constraints||(t.sessionDescriptionHandlerOptions.constraints=this.constraints),e.accept(t)):Promise.reject(new Error("Session not instance of Invitation.")):Promise.reject(new Error("Session does not exist."))}async decline(e){return this.logger.log(`[${e.id}] Rejecting Invitation...`),this.sessionExists(e)?e instanceof ue?e.reject():Promise.reject(new Error("Session not instance of Invitation.")):Promise.reject(new Error("Session does not exist."))}async hold(e){return this.logger.log(`[${e.id}] Holding session...`),this.setHold(e,!0)}async unhold(e){return this.logger.log(`[${e.id}] Unholding session...`),this.setHold(e,!1)}isHeld(e){const t=this.sessionManaged(e);return t?t.held:!1}mute(e){this.logger.log(`[${e.id}] Disabling media tracks...`),this.setMute(e,!0)}unmute(e){this.logger.log(`[${e.id}] Enabling media tracks...`),this.setMute(e,!1)}isMuted(e){const t=this.sessionManaged(e);return t?t.muted:!1}async sendDTMF(e,t){if(this.logger.log(`[${e.id}] Sending DTMF...`),!/^[0-9A-D#*,]$/.exec(t))return Promise.reject(new Error("Invalid DTMF tone."));if(!this.sessionExists(e))return Promise.reject(new Error("Session does not exist."));if(this.logger.log(`[${e.id}] Sending DTMF tone: ${t}`),this.options.sendDTMFUsingSessionDescriptionHandler)return e.sessionDescriptionHandler?e.sessionDescriptionHandler.sendDtmf(t)?Promise.resolve():Promise.reject(new Error("Failed to send DTMF")):Promise.reject(new Error("Session desciption handler undefined."));{const n={body:{contentDisposition:"render",contentType:"application/dtmf-relay",content:"Signal="+t+`\r
|
|
64
|
-
Duration=`+2e3}};return e.info({requestOptions:n}).then(()=>{})}}async transfer(e,t,i){if(this.logger.log(`[${e.id}] Referring session...`),t instanceof
|
|
65
|
-
`,2);if(n.length!==2){i.reject();return}let a;const d=/^(Signal\s*?=\s*?)([0-9A-D#*]{1})(\s)?.*/;if(n[0]!==void 0&&d.test(n[0])&&(a=n[0].replace(d,"$2")),!a){i.reject();return}let f;const h=/^(Duration\s?=\s?)([0-9]{1,4})(\s)?.*/;if(n[1]!==void 0&&h.test(n[1])&&(f=parseInt(n[1].replace(h,"$2"),10)),!f){i.reject();return}i.accept().then(()=>{if(this.delegate&&this.delegate.onCallDTMFReceived){if(!a||!f)throw new Error("Tone or duration undefined.");this.delegate.onCallDTMFReceived(e,a,f)}}).catch(w=>{this.logger.error(w.message)})},e.delegate.onRefer=i=>{i.accept().then(()=>this.sendInvite(i.makeInviter(t),t)).catch(s=>{this.logger.error(s.message)})}}optionsPingRun(e,t,i){if(this.options.optionsPingInterval<1)throw new Error("Invalid options ping interval.");this.optionsPingRunning||(this.optionsPingRunning=!0,this.optionsPingTimeout=setTimeout(()=>{this.optionsPingTimeout=void 0;const s=()=>{this.optionsPingFailure=!1,this.optionsPingRunning&&(this.optionsPingRunning=!1,this.optionsPingRun(e,t,i))},r=()=>{this.logger.error("OPTIONS ping failed"),this.optionsPingFailure=!0,this.optionsPingRunning=!1,this.userAgent.transport.disconnect().catch(d=>this.logger.error(d))},n=this.userAgent.userAgentCore,a=n.makeOutgoingRequestMessage("OPTIONS",e,t,i,{});this.optionsPingRequest=n.request(a,{onAccept:()=>{this.optionsPingRequest=void 0,s()},onReject:d=>{this.optionsPingRequest=void 0,d.message.statusCode===408||d.message.statusCode===503?r():s()}})},this.options.optionsPingInterval*1e3))}optionsPingStart(){this.logger.log("OPTIONS pings started");let e,t,i;if(this.options.optionsPingRequestURI){if(e=K.makeURI(this.options.optionsPingRequestURI),!e)throw new Error("Failed to create Request URI.");t=this.userAgent.contact.uri.clone(),i=this.userAgent.contact.uri.clone()}else if(this.options.aor){const s=K.makeURI(this.options.aor);if(!s)throw new Error("Failed to create URI.");e=s.clone(),e.user=void 0,t=s.clone(),i=s.clone()}else{this.logger.error("You have enabled sending OPTIONS pings and as such you must provide either a) an AOR to register, or b) an RURI to use for the target of the OPTIONS ping requests. ");return}this.optionsPingRun(e,t,i)}optionsPingStop(){this.logger.log("OPTIONS pings stopped"),this.optionsPingRunning=!1,this.optionsPingFailure=!1,this.optionsPingRequest&&(this.optionsPingRequest.dispose(),this.optionsPingRequest=void 0),this.optionsPingTimeout&&(clearTimeout(this.optionsPingTimeout),this.optionsPingTimeout=void 0)}async sendInvite(e,t,i){return this.initSession(e,t),e.invite(i).then(()=>{this.logger.log(`[${e.id}] Sent INVITE`)})}sessionAdd(e){const t=this.options.managedSessionFactory(this,e);this.managedSessions.push(t)}sessionExists(e){return this.sessionManaged(e)!==void 0}sessionManaged(e){return this.managedSessions.find(t=>t.session.id===e.id)}sessionRemove(e){this.managedSessions=this.managedSessions.filter(t=>t.session.id!==e.id)}async setHold(e,t){if(!this.sessionExists(e))return Promise.reject(new Error("Session does not exist."));if(this.isHeld(e)===t)return Promise.resolve();if(!(e.sessionDescriptionHandler instanceof F))throw new Error("Session's session description handler not instance of SessionDescriptionHandler.");const s={requestDelegate:{onAccept:()=>{const a=this.sessionManaged(e);a!==void 0&&(a.held=t,this.enableReceiverTracks(e,!a.held),this.enableSenderTracks(e,!a.held&&!a.muted),this.delegate&&this.delegate.onCallHold&&this.delegate.onCallHold(e,a.held))},onReject:()=>{this.logger.warn(`[${e.id}] Re-invite request was rejected`);const a=this.sessionManaged(e);a!==void 0&&(a.held=!t,this.enableReceiverTracks(e,!a.held),this.enableSenderTracks(e,!a.held&&!a.muted),this.delegate&&this.delegate.onCallHold&&this.delegate.onCallHold(e,a.held))}}},r=e.sessionDescriptionHandlerOptionsReInvite;r.hold=t,e.sessionDescriptionHandlerOptionsReInvite=r;const n=this.sessionManaged(e);if(!n)throw new Error("Managed session is undefiend.");return n.held=t,e.invite(s).then(()=>{const a=this.sessionManaged(e);a!==void 0&&(this.enableReceiverTracks(e,!a.held),this.enableSenderTracks(e,!a.held&&!a.muted))}).catch(a=>{throw n.held=!t,a instanceof be&&this.logger.error(`[${e.id}] A hold request is already in progress.`),a})}setMute(e,t){if(!this.sessionExists(e)){this.logger.warn(`[${e.id}] A session is required to enabled/disable media tracks`);return}if(e.state!==m.Established){this.logger.warn(`[${e.id}] An established session is required to enable/disable media tracks`);return}const i=this.sessionManaged(e);i!==void 0&&(i.muted=t,this.enableSenderTracks(e,!i.held&&!i.muted))}setupLocalMedia(e){const t=this.sessionManaged(e);if(!t)throw new Error("Managed session does not exist.");const i=typeof this.options.media.local=="function"?this.options.media.local(e):this.options.media.local;t.mediaLocal=i;const s=i?.video;if(s){const r=this.getLocalMediaStream(e);if(!r)throw new Error("Local media stream undefiend.");s.srcObject=r,s.volume=0,s.play().catch(n=>{this.logger.error(`[${e.id}] Failed to play local media`),this.logger.error(n.message)})}}setupRemoteMedia(e){const t=this.sessionManaged(e);if(!t)throw new Error("Managed session does not exist.");const i=typeof this.options.media.remote=="function"?this.options.media.remote(e):this.options.media.remote;t.mediaRemote=i;const s=i?.video||i?.audio;if(s){const r=this.getRemoteMediaStream(e);if(!r)throw new Error("Remote media stream undefiend.");s.autoplay=!0,s.srcObject=r,s.play().catch(n=>{this.logger.error(`[${e.id}] Failed to play remote media`),this.logger.error(n.message)}),r.onaddtrack=()=>{this.logger.log("Remote media onaddtrack"),s.load(),s.play().catch(n=>{this.logger.error(`[${e.id}] Failed to play remote media`),this.logger.error(n.message)})}}}async terminate(e){switch(this.logger.log(`[${e.id}] Terminating...`),e.state){case m.Initial:if(e instanceof De)return e.cancel().then(()=>{this.logger.log(`[${e.id}] Inviter never sent INVITE (canceled)`)});if(e instanceof ue)return e.reject().then(()=>{this.logger.log(`[${e.id}] Invitation rejected (sent 480)`)});throw new Error("Unknown session type.");case m.Establishing:if(e instanceof De)return e.cancel().then(()=>{this.logger.log(`[${e.id}] Inviter canceled (sent CANCEL)`)});if(e instanceof ue)return e.reject().then(()=>{this.logger.log(`[${e.id}] Invitation rejected (sent 480)`)});throw new Error("Unknown session type.");case m.Established:return e.bye().then(()=>{this.logger.log(`[${e.id}] Session ended (sent BYE)`)});case m.Terminating:break;case m.Terminated:break;default:throw new Error("Unknown state")}return this.logger.log(`[${e.id}] Terminating in state ${e.state}, no action taken`),Promise.resolve()}}class mi{constructor(e,t={}){this.session=void 0,this.delegate=t.delegate,this.options=Object.assign({},t);const i={aor:this.options.aor,delegate:{onCallAnswered:()=>{var s,r;return(r=(s=this.delegate)===null||s===void 0?void 0:s.onCallAnswered)===null||r===void 0?void 0:r.call(s)},onCallCreated:s=>{var r,n;this.session=s,(n=(r=this.delegate)===null||r===void 0?void 0:r.onCallCreated)===null||n===void 0||n.call(r)},onCallReceived:()=>{var s,r;return(r=(s=this.delegate)===null||s===void 0?void 0:s.onCallReceived)===null||r===void 0?void 0:r.call(s)},onCallHangup:()=>{var s,r;this.session=void 0,!((s=this.delegate)===null||s===void 0)&&s.onCallHangup&&((r=this.delegate)===null||r===void 0||r.onCallHangup())},onCallHold:(s,r)=>{var n,a;return(a=(n=this.delegate)===null||n===void 0?void 0:n.onCallHold)===null||a===void 0?void 0:a.call(n,r)},onCallDTMFReceived:(s,r,n)=>{var a,d;return(d=(a=this.delegate)===null||a===void 0?void 0:a.onCallDTMFReceived)===null||d===void 0?void 0:d.call(a,r,n)},onMessageReceived:s=>{var r,n;return(n=(r=this.delegate)===null||r===void 0?void 0:r.onMessageReceived)===null||n===void 0?void 0:n.call(r,s.request.body)},onRegistered:()=>{var s,r;return(r=(s=this.delegate)===null||s===void 0?void 0:s.onRegistered)===null||r===void 0?void 0:r.call(s)},onUnregistered:()=>{var s,r;return(r=(s=this.delegate)===null||s===void 0?void 0:s.onUnregistered)===null||r===void 0?void 0:r.call(s)},onServerConnect:()=>{var s,r;return(r=(s=this.delegate)===null||s===void 0?void 0:s.onServerConnect)===null||r===void 0?void 0:r.call(s)},onServerDisconnect:()=>{var s,r;return(r=(s=this.delegate)===null||s===void 0?void 0:s.onServerDisconnect)===null||r===void 0?void 0:r.call(s)}},maxSimultaneousSessions:1,media:this.options.media,reconnectionAttempts:this.options.reconnectionAttempts,reconnectionDelay:this.options.reconnectionDelay,registererOptions:this.options.registererOptions,sendDTMFUsingSessionDescriptionHandler:this.options.sendDTMFUsingSessionDescriptionHandler,userAgentOptions:this.options.userAgentOptions};this.sessionManager=new Ge(e,i),this.logger=this.sessionManager.userAgent.getLogger("sip.SimpleUser")}get id(){return this.options.userAgentOptions&&this.options.userAgentOptions.displayName||"Anonymous"}get localMediaStream(){return this.session&&this.sessionManager.getLocalMediaStream(this.session)}get remoteMediaStream(){return this.session&&this.sessionManager.getRemoteMediaStream(this.session)}get localAudioTrack(){return this.session&&this.sessionManager.getLocalAudioTrack(this.session)}get localVideoTrack(){return this.session&&this.sessionManager.getLocalVideoTrack(this.session)}get remoteAudioTrack(){return this.session&&this.sessionManager.getRemoteAudioTrack(this.session)}get remoteVideoTrack(){return this.session&&this.sessionManager.getRemoteVideoTrack(this.session)}connect(){return this.logger.log(`[${this.id}] Connecting UserAgent...`),this.sessionManager.connect()}disconnect(){return this.logger.log(`[${this.id}] Disconnecting UserAgent...`),this.sessionManager.disconnect()}isConnected(){return this.sessionManager.isConnected()}register(e){return this.logger.log(`[${this.id}] Registering UserAgent...`),this.sessionManager.register(e)}unregister(e){return this.logger.log(`[${this.id}] Unregistering UserAgent...`),this.sessionManager.unregister(e)}call(e,t,i){return this.logger.log(`[${this.id}] Beginning Session...`),this.session?Promise.reject(new Error("Session already exists.")):this.sessionManager.call(e,t,i).then(()=>{})}hangup(){return this.logger.log(`[${this.id}] Hangup...`),this.session?this.sessionManager.hangup(this.session).then(()=>{this.session=void 0}):Promise.reject(new Error("Session does not exist."))}answer(e){return this.logger.log(`[${this.id}] Accepting Invitation...`),this.session?this.sessionManager.answer(this.session,e):Promise.reject(new Error("Session does not exist."))}decline(){return this.logger.log(`[${this.id}] rejecting Invitation...`),this.session?this.sessionManager.decline(this.session):Promise.reject(new Error("Session does not exist."))}hold(){return this.logger.log(`[${this.id}] holding session...`),this.session?this.sessionManager.hold(this.session):Promise.reject(new Error("Session does not exist."))}unhold(){return this.logger.log(`[${this.id}] unholding session...`),this.session?this.sessionManager.unhold(this.session):Promise.reject(new Error("Session does not exist."))}isHeld(){return this.session?this.sessionManager.isHeld(this.session):!1}mute(){return this.logger.log(`[${this.id}] disabling media tracks...`),this.session&&this.sessionManager.mute(this.session)}unmute(){return this.logger.log(`[${this.id}] enabling media tracks...`),this.session&&this.sessionManager.unmute(this.session)}isMuted(){return this.session?this.sessionManager.isMuted(this.session):!1}sendDTMF(e){return this.logger.log(`[${this.id}] sending DTMF...`),this.session?this.sessionManager.sendDTMF(this.session,e):Promise.reject(new Error("Session does not exist."))}message(e,t){return this.logger.log(`[${this.id}] sending message...`),this.sessionManager.message(e,t)}}const wi=15e3,yi=15e3,We=(o,e,t)=>{const i=String(o?.name||o?.code||"").trim(),s=new Error(e);return s.name=i||"MediaAccessError",s.code=t,s.cause=o,s},Ke=o=>{const e=new Error(o);return e.name="SipClientLifecycleCancelledError",e.code="sip_client_replaced",e},ze=async(o,e="call")=>{const t=String(o?.name||o?.code||"").trim(),i=String(o?.message||"").trim(),s=`${t} ${i}`.toLowerCase();let r="";try{if(typeof navigator<"u"&&navigator.permissions?.query){const n=await navigator.permissions.query({name:"microphone"});r=String(n?.state||"").trim().toLowerCase()}}catch{r=""}return r==="denied"||t==="NotAllowedError"||t==="SecurityError"||s.includes("notallowederror")||s.includes("permission denied")||s.includes("permission dismissed")||s.includes("microphone permission")||s.includes("getusermedia() no permission")?We(o,`浏览器未授予麦克风权限,无法${e==="answer"?"接听来电":"发起通话"}。请点击地址栏的麦克风权限并选择“允许”,然后刷新页面重试。`,"media_permission_denied"):t==="NotFoundError"||t==="DevicesNotFoundError"||s.includes("notfounderror")||s.includes("requested device not found")||s.includes("no audio input device")?We(o,"未检测到可用的麦克风设备,无法建立语音通话。请连接耳麦或启用系统麦克风后重试。","media_device_not_found"):t==="NotReadableError"||t==="TrackStartError"||s.includes("notreadableerror")||s.includes("could not start audio source")?We(o,"麦克风当前被系统或其他应用占用,无法建立语音通话。请关闭占用麦克风的程序后重试。","media_device_unavailable"):o},bi=async(o="call")=>{if(typeof navigator>"u"||!navigator.mediaDevices?.getUserMedia)return null;let e=null;try{return e=await navigator.mediaDevices.getUserMedia({audio:!0,video:!1}),e}catch(t){throw await ze(t,o)}};class vi{constructor(e,t={}){this.account={...e},this.remoteAudioElementId=t.remoteAudioElementId||"sipRemoteAudio",this.remoteAudioElement=t.remoteAudioElement||null,this.onStateChange=t.onStateChange,this.onError=t.onError,this.onAudioLevel=t.onAudioLevel,this.onAudioFrame=t.onAudioFrame,this.simpleUser=null,this.connected=!1,this.registered=!1,this.active=!1,this.lastFailureMeta=null,this.audioContext=null,this.audioMonitors={local:null,remote:null},this.audioTrackMeta={local:null,remote:null},this.ringbackAudio=null,this.ringbackPlaying=!1,this.incomingAudio=null,this.incomingPlaying=!1,this.hangupInitiatedByLocal=!1,this.ringbackToneUrl=this._resolveToneUrl(t.ringbackTone||"ringback1.wav"),this.incomingToneUrl=this._resolveToneUrl(t.incomingTone||"ring1.wav"),this.pendingPlaybackTasks=new Map,this.audioUnlockHandler=null,this.lastSessionMeta=null,this.ensureReadyPromise=null,this.connectionWaiters=new Set,this.registrationWaiters=new Set,this.connectionConfirmTimeoutMs=Number.isFinite(Number(t.connectionConfirmTimeoutMs))?Number(t.connectionConfirmTimeoutMs):wi,this.registrationConfirmTimeoutMs=Number.isFinite(Number(t.registrationConfirmTimeoutMs))?Number(t.registrationConfirmTimeoutMs):yi,this.peerConnectionDebug={attached:!1,events:[],iceCandidates:[],iceCandidateErrors:[]}}getAudioTrackMeta(e){return e&&this.audioTrackMeta?.[e]?{...this.audioTrackMeta[e]}:null}matchesAccount(e){return this.account?this.account.sip_username===e.sip_username&&this.account.sip_domain===e.sip_domain&&(this.account.port||"443")===(e.port||"443")&&(this.account.webrtc_url||"")===(e.webrtc_url||"")&&JSON.stringify(this.account.ice_servers||[])===JSON.stringify(e.ice_servers||[]):!1}_getRemoteAudioElement(){if(this.remoteAudioElement instanceof HTMLAudioElement)return this.remoteAudioElement.autoplay=!0,this.remoteAudioElement.playsInline=!0,this.remoteAudioElement.muted=!1,this.remoteAudioElement.volume=1,this.remoteAudioElement;const e=document.getElementById(this.remoteAudioElementId);if(!(e instanceof HTMLAudioElement))throw new Error("找不到用于播放远端音频的 audio 元素");return e.autoplay=!0,e.playsInline=!0,e.muted=!1,e.volume=1,e}_getPeerConnection(){const t=this.simpleUser?.session?.sessionDescriptionHandler;return t?.peerConnection||t?._peerConnection||null}_summarizeSessionDescription(e){if(!e?.sdp)return null;const t=String(e.sdp).split(/\r?\n/).map(s=>s.trim()).filter(Boolean),i=["o=","c=","m=","a=ice-","a=candidate","a=setup:","a=fingerprint:","a=rtcp-mux","a=mid:"];return{type:e.type||"",lineCount:t.length,importantLines:t.filter(s=>i.some(r=>s.startsWith(r))),candidateLines:t.filter(s=>s.startsWith("a=candidate")),iceLines:t.filter(s=>s.startsWith("a=ice-"))}}async getMediaDiagnostics(){const e=this._getPeerConnection();this._ensurePeerConnectionDebug(e);const t=document.getElementById(this.remoteAudioElementId),i={hasPeerConnection:!!e,signalingState:e?.signalingState||"",connectionState:e?.connectionState||"",iceConnectionState:e?.iceConnectionState||"",iceGatheringState:e?.iceGatheringState||"",peerConnectionEvents:this.peerConnectionDebug.events.slice(-20),iceCandidateErrors:this.peerConnectionDebug.iceCandidateErrors.slice(-20),localDescription:this._summarizeSessionDescription(e?.localDescription),remoteDescription:this._summarizeSessionDescription(e?.remoteDescription),remoteAudio:t instanceof HTMLAudioElement?{paused:t.paused,muted:t.muted,volume:t.volume,readyState:t.readyState,currentTime:t.currentTime,srcObjectTracks:t.srcObject?.getTracks?.().map(n=>({kind:n.kind,enabled:n.enabled,muted:n.muted,readyState:n.readyState,id:n.id}))||[]}:null};if(!e||typeof e.getStats!="function")return i;const s=await e.getStats(),r={inboundAudio:null,outboundAudio:null,selectedCandidatePair:null,localCandidate:null,remoteCandidate:null,localCandidates:[],remoteCandidates:[],candidatePairs:[]};for(const n of s.values()){if(n.type==="inbound-rtp"&&n.kind==="audio"&&!n.isRemote&&(r.inboundAudio={packetsReceived:n.packetsReceived||0,bytesReceived:n.bytesReceived||0,packetsLost:n.packetsLost||0,jitter:n.jitter||0,codecId:n.codecId||"",transportId:n.transportId||""}),n.type==="outbound-rtp"&&n.kind==="audio"&&!n.isRemote&&(r.outboundAudio={packetsSent:n.packetsSent||0,bytesSent:n.bytesSent||0,retransmittedPacketsSent:n.retransmittedPacketsSent||0,codecId:n.codecId||"",transportId:n.transportId||""}),n.type==="transport"&&n.selectedCandidatePairId&&!r.selectedCandidatePair){const a=s.get(n.selectedCandidatePairId);a&&(r.selectedCandidatePair={state:a.state||"",localCandidateId:a.localCandidateId||"",remoteCandidateId:a.remoteCandidateId||"",bytesSent:a.bytesSent||0,bytesReceived:a.bytesReceived||0,currentRoundTripTime:a.currentRoundTripTime||0},r.localCandidate=s.get(a.localCandidateId)||null,r.remoteCandidate=s.get(a.remoteCandidateId)||null)}n.type==="local-candidate"&&r.localCandidates.push({id:n.id||"",candidateType:n.candidateType||"",protocol:n.protocol||"",address:n.address||n.ip||"",port:n.port||0,relayProtocol:n.relayProtocol||"",url:n.url||"",networkType:n.networkType||""}),n.type==="remote-candidate"&&r.remoteCandidates.push({id:n.id||"",candidateType:n.candidateType||"",protocol:n.protocol||"",address:n.address||n.ip||"",port:n.port||0,relayProtocol:n.relayProtocol||"",url:n.url||""}),n.type==="candidate-pair"&&r.candidatePairs.push({id:n.id||"",state:n.state||"",nominated:!!n.nominated,writable:!!n.writable,readable:!!n.readable,requestsSent:n.requestsSent||0,requestsReceived:n.requestsReceived||0,responsesSent:n.responsesSent||0,responsesReceived:n.responsesReceived||0,bytesSent:n.bytesSent||0,bytesReceived:n.bytesReceived||0,currentRoundTripTime:n.currentRoundTripTime||0,localCandidateId:n.localCandidateId||"",remoteCandidateId:n.remoteCandidateId||""})}return{...i,...r}}_ensurePeerConnectionDebug(e){if(!e||this.peerConnectionDebug.attached)return;this.peerConnectionDebug.attached=!0;const t=(i,s={})=>{this.peerConnectionDebug.events.push({type:i,timestamp:new Date().toISOString(),...s}),this.peerConnectionDebug.events.length>100&&(this.peerConnectionDebug.events=this.peerConnectionDebug.events.slice(-100))};e.addEventListener("connectionstatechange",()=>{t("connectionstatechange",{connectionState:e.connectionState||""})}),e.addEventListener("iceconnectionstatechange",()=>{t("iceconnectionstatechange",{iceConnectionState:e.iceConnectionState||""})}),e.addEventListener("icegatheringstatechange",()=>{t("icegatheringstatechange",{iceGatheringState:e.iceGatheringState||""})}),e.addEventListener("signalingstatechange",()=>{t("signalingstatechange",{signalingState:e.signalingState||""})}),e.addEventListener("icecandidate",i=>{const s=i?.candidate;if(!s){t("icecandidate-complete");return}const r={candidate:s.candidate||"",address:s.address||"",port:s.port||0,protocol:s.protocol||"",type:s.type||"",foundation:s.foundation||"",relatedAddress:s.relatedAddress||"",relatedPort:s.relatedPort||0,sdpMid:s.sdpMid||"",sdpMLineIndex:s.sdpMLineIndex??null};this.peerConnectionDebug.iceCandidates.push(r),this.peerConnectionDebug.iceCandidates.length>100&&(this.peerConnectionDebug.iceCandidates=this.peerConnectionDebug.iceCandidates.slice(-100)),t("icecandidate",r)}),e.addEventListener("icecandidateerror",i=>{const s={address:i?.address||"",port:i?.port||0,url:i?.url||"",errorCode:i?.errorCode||0,errorText:i?.errorText||""};this.peerConnectionDebug.iceCandidateErrors.push({timestamp:new Date().toISOString(),...s}),this.peerConnectionDebug.iceCandidateErrors.length>100&&(this.peerConnectionDebug.iceCandidateErrors=this.peerConnectionDebug.iceCandidateErrors.slice(-100)),t("icecandidateerror",s)}),e.addEventListener("track",i=>{t("track",{streams:Array.isArray(i?.streams)?i.streams.map(s=>({id:s.id,audioTracks:s.getAudioTracks().map(r=>({id:r.id,enabled:r.enabled,muted:r.muted,readyState:r.readyState}))})):[]})})}_createSimpleUser(){const{sip_username:e,sip_password:t,sip_domain:i,port:s,webrtc_url:r,ice_servers:n}=this.account,a=s||"443",d=r||(/^wss?:\/\//.test(i)?i:`wss://${i}:${a}`),h={aor:`sip:${e}@${i}`,media:{constraints:{audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0},video:!1},remote:{audio:this._getRemoteAudioElement()}},userAgentOptions:{authorizationUsername:e,authorizationPassword:t,sessionDescriptionHandlerFactoryOptions:{peerConnectionConfiguration:n?.length?{iceServers:n,iceTransportPolicy:"all"}:void 0}},registererOptions:{expires:1800}},w=new mi(d,h);return w.delegate={onServerConnect:()=>{this.connected=!0,this._resolveConnectionWaiters(),this.onStateChange&&this.onStateChange("connected",this.getConnectionSnapshot())},onServerDisconnect:S=>{this.connected=!1,this.registered=!1,this.active=!1,this._rejectConnectionWaiters(S||new Error("呼叫服务器已断开")),this._rejectRegistrationWaiters(S||new Error("呼叫服务器已断开")),this.onError&&this.onError(S||new Error("呼叫服务器已断开")),this.onStateChange&&this.onStateChange("disconnected",this.getConnectionSnapshot()),this._stopRingback(),this._stopIncomingTone()},onRegistered:()=>{this.registered=!0,this._resolveRegistrationWaiters(),this.onStateChange&&this.onStateChange("registered",this.getConnectionSnapshot())},onUnregistered:()=>{this.registered=!1,this._rejectRegistrationWaiters(new Error("SIP 注册已被取消或失效。")),this.onStateChange&&this.onStateChange("unregistered",this.getConnectionSnapshot())},onCallCreated:()=>{const S=this._isIncomingSession();this.lastSessionMeta=this._buildIncomingCallMeta(),!S&&this.onStateChange&&(this.onStateChange("dialing"),this._scheduleLocalMonitor())},onCallReceived:()=>{this.lastSessionMeta=this._buildIncomingCallMeta(),this._playIncomingTone(),this.onStateChange&&this.onStateChange("incoming",this._buildIncomingCallMeta())},onCallAnswered:()=>{this.active=!0,this.lastSessionMeta=this._buildIncomingCallMeta(),this.onStateChange&&this.onStateChange("answered",this._buildIncomingCallMeta()),this._stopRingback(),this._stopIncomingTone(),this._scheduleRemoteMonitor()},onCallHangup:()=>{const S=this.active;if(this.active=!1,this.onStateChange){const x=this.lastFailureMeta?{...this.lastFailureMeta}:{};x.hangupSource=this.hangupInitiatedByLocal?"local":S?"remote":"unknown";const I=this.lastSessionMeta||this._buildIncomingCallMeta();I&&Object.keys(I).length>0&&(x.callMeta=I),this.onStateChange("terminated",x)}this.hangupInitiatedByLocal=!1,this._stopAllAudioMonitors(),this._reportAudioSilence(),this._stopRingback(),this._stopIncomingTone(),this.lastFailureMeta=null,this.lastSessionMeta=null}},w}_encodeSipUserPart(e){if(!e)return"";let t=e;try{t=decodeURIComponent(e)}catch{t=e}return encodeURIComponent(t).replace(/%2B/g,"+")}_normalizeSipDestination(e){const t=(e||"").trim();if(!t)throw new Error("呼叫目标地址不能为空");const i=t.match(/^(sips?:)/i),s=i?i[1].toLowerCase():"sip:",r=i?t.slice(i[1].length):t,n=r.indexOf("@");if(n===-1)return`${s}${this._encodeSipUserPart(r)}`;const a=r.slice(0,n),d=r.slice(n+1),f=this._encodeSipUserPart(a);return`${s}${f}@${d}`}_isIncomingSession(){if(!this.simpleUser||!this.simpleUser.session)return!1;if(typeof ue<"u"&&this.simpleUser.session instanceof ue)return!0;const e=this.simpleUser.session;return!!(e&&e.incomingInviteRequest)}_buildIncomingCallMeta(){const e=this.simpleUser?.session;if(!e||!e.remoteIdentity)return{};const t=e.remoteIdentity,i=t?.uri;return{displayName:t?.displayName||t?.friendlyName||"",uri:typeof t?.toString=="function"?t.toString():i?.toString?.()||"",user:i?.user||"",host:i?.host||"",direction:this._isIncomingSession()?"inbound":"outbound"}}_assertSimpleUserIsCurrent(e,t="当前操作"){if(!(e&&this.simpleUser===e&&this.account))throw Ke(`SIP 客户端已重置,已取消${t}。`)}_resolveRegistrationWaiters(){if(!this.registrationWaiters.size)return;const e=Array.from(this.registrationWaiters);this.registrationWaiters.clear(),e.forEach(t=>{try{t.resolve()}catch{}})}_rejectRegistrationWaiters(e){if(!this.registrationWaiters.size)return;const t=Array.from(this.registrationWaiters);this.registrationWaiters.clear();const i=e instanceof Error?e:new Error("SIP 注册未完成即已中断。");t.forEach(s=>{try{s.reject(i)}catch{}})}_resolveConnectionWaiters(){if(!this.connectionWaiters.size)return;const e=Array.from(this.connectionWaiters);this.connectionWaiters.clear(),e.forEach(t=>{try{t.resolve()}catch{}})}_rejectConnectionWaiters(e){if(!this.connectionWaiters.size)return;const t=Array.from(this.connectionWaiters);this.connectionWaiters.clear();const i=e instanceof Error?e:new Error("SIP 连接未完成即已中断。");t.forEach(s=>{try{s.reject(i)}catch{}})}_waitForConnectionConfirmation(e=this.connectionConfirmTimeoutMs){return this.connected?Promise.resolve():new Promise((t,i)=>{const s={resolve:()=>{clearTimeout(r),t()},reject:n=>{clearTimeout(r),i(n)}},r=setTimeout(()=>{this.connectionWaiters.delete(s);const n=this.account?.internal_number||this.account?.account_key||this.account?.sip_username||"当前账号";i(new Error(`${n} 浏览器连接超时,未收到 SIP 服务器连接确认。`))},e);this.connectionWaiters.add(s)})}_waitForRegistrationConfirmation(e=this.registrationConfirmTimeoutMs){return this.registered?Promise.resolve():new Promise((t,i)=>{const s={resolve:()=>{clearTimeout(r),t()},reject:n=>{clearTimeout(r),i(n)}},r=setTimeout(()=>{this.registrationWaiters.delete(s);const n=this.account?.internal_number||this.account?.account_key||this.account?.sip_username||"当前账号";i(new Error(`${n} 浏览器注册超时,信令已连接但未收到注册确认。`))},e);this.registrationWaiters.add(s)})}_captureRegistrationDiagnostics(){return{snapshot:this.getConnectionSnapshot(),shouldBeRegistered:!!this.simpleUser?.sessionManager?.shouldBeRegistered,hasRegisterer:!!this.simpleUser?.sessionManager?.registerer}}_shouldRecoverFromConnectedWithoutRegistration(e){return!!(e?.snapshot?.connected&&!e?.snapshot?.registered&&!e?.shouldBeRegistered&&!e?.hasRegisterer)}async _ensureRegistration(e){try{this._assertSimpleUserIsCurrent(e,"注册流程"),await e.register(),this._assertSimpleUserIsCurrent(e,"注册流程"),this.registered||(await this._waitForRegistrationConfirmation(),this._assertSimpleUserIsCurrent(e,"注册确认"))}catch(t){throw this.onError&&this.onError(t),t}}async ensureReady(){if(this.ensureReadyPromise)return this.ensureReadyPromise;const e=(async()=>{let t=this.simpleUser;if(t||(t=this._createSimpleUser(),this.simpleUser=t),!this.connected){let i=null;const s=t.connect().catch(r=>(i=r,null));if(this.connected||await Promise.race([s,this._waitForConnectionConfirmation()]),this.connected||await s,i)throw i;this.connected||await this._waitForConnectionConfirmation(),this._assertSimpleUserIsCurrent(t,"连接流程"),this.connected=!0,this.onStateChange&&this.onStateChange("connected",this.getConnectionSnapshot())}if(!this.registered){let i=null;try{await this._ensureRegistration(t)}catch(r){i=r}let s=this._captureRegistrationDiagnostics();if(i&&this._shouldRecoverFromConnectedWithoutRegistration(s)){console.info("SIP 客户端首次建连后未真正进入注册流程,开始立即补注册。",{accountKey:this.account?.internal_number||this.account?.account_key||this.account?.sip_username||null,snapshot:s.snapshot}),await new Promise(r=>window.setTimeout(r,200));try{await this._ensureRegistration(t)}catch(r){i=i||r}s=this._captureRegistrationDiagnostics()}if(i&&!(s?.snapshot?.connected&&s?.snapshot?.registered))throw i}})().finally(()=>{this.ensureReadyPromise===e&&(this.ensureReadyPromise=null)});return this.ensureReadyPromise=e,e}getConnectionSnapshot(){const e=this.simpleUser,t=typeof e?.isConnected=="function"?e.isConnected():!!this.connected,i=typeof e?.isRegistered=="function"?e.isRegistered():!!this.registered;return{connected:t,registered:i,active:!!this.active,sipDomain:this.account?.sip_domain||"",transportUrl:this.account?.webrtc_url||""}}async disconnect(e={}){const{unregister:t=!0}=e||{};if(!this.simpleUser){this.connected=!1,this.registered=!1,this.onStateChange&&this.onStateChange("disconnected",this.getConnectionSnapshot());return}const i=[];t&&this.registered&&i.push(this.simpleUser.unregister().catch(s=>{this.onError&&this.onError(s)})),this.connected&&i.push(this.simpleUser.disconnect().catch(s=>{this.onError&&this.onError(s)})),await Promise.all(i),this.connected=!1,this.registered=!1,this.active=!1,this._stopAllAudioMonitors(),this._reportAudioSilence(),this._stopRingback(),this._stopIncomingTone(),this._clearAutoplayUnlockTasks(),this.onStateChange&&this.onStateChange("disconnected",this.getConnectionSnapshot())}async reconnect(){await this.disconnect(),await this.ensureReady()}async call(e,t){if(!e)throw new Error("电话号码不能为空");this.lastFailureMeta=null,this.hangupInitiatedByLocal=!1,await this.ensureReady();const i=String(e).trim();let s;/^sips?:/i.test(i)?s=i:i.includes("@")?s=`sip:${i}`:s=`sip:${i}@${this.account.sip_domain}`,s=this._normalizeSipDestination(s);const r=this._createInviteRequestDelegate(t),n=this._mergeInviteOptions(t,r);try{await this._preflightAudioAccess("call"),await this.simpleUser.call(s,void 0,n),this._scheduleLocalMonitor(),this._stopIncomingTone()}catch(a){const d=await this._normalizeMediaAccessError(a,"call");throw this.onError&&this.onError(d),this.lastFailureMeta={source:"invite-exception",code:d?.code||null,message:d?.message||"呼叫请求失败",timestamp:new Date().toISOString()},this.onStateChange&&this.onStateChange("failed",{...this.lastFailureMeta}),d}}async _preflightAudioAccess(e="call"){let t=null;try{t=await bi(e)}catch(i){const s=await ze(i,e);throw this.onError&&this.onError(s),this.lastFailureMeta={source:"media-preflight",code:s?.code||null,message:s?.message||"媒体设备检查失败",timestamp:new Date().toISOString()},this.onStateChange&&this.onStateChange("failed",{...this.lastFailureMeta}),s}finally{t?.getTracks?.().forEach(i=>{try{i.stop()}catch{}})}}_mergeInviteOptions(e,t){const i={...e||{}};return i.requestDelegate=t.requestDelegate,i}_handleInviteProgress(e){const t=e?.message;if(!t)return;const i=t.statusCode||0;if(i>=180&&i<200){const s=this._extractResponseMeta("progress",e);console.info("[CALL] 呼叫收到临时响应",s),this._isIncomingSession()||(this.onStateChange&&this.onStateChange(i===180?"ringing":"dialing",s),i===180&&this._playRingback())}}_handleInviteFailure(e,t){const i=this._extractResponseMeta(e,t);this.lastFailureMeta=i,console.warn("[CALL] 呼叫失败",i),this._stopRingback(),this._stopIncomingTone(),this._stopAllAudioMonitors(),this._reportAudioSilence(),this.onStateChange&&this.onStateChange("failed",{...i}),this.onError&&i.message&&this.onError(new Error(i.message))}_extractResponseMeta(e,t){const i=t?.message,s=i?.statusCode||null,r=(i?.reasonPhrase||"").trim(),n=this._getHeaderValue(i,"Warning"),a=this._getHeaderValue(i,"Reason"),d=this._getHeaderValue(i,"Retry-After"),f=typeof i?.body=="string"?i.body.trim():"",w=[s,r].filter(Boolean).join(" ").trim()||n||a||f||"呼叫未建立";return{source:"invite-response",stage:e,status:s,reason:r,warning:n,cause:a,retryAfter:d,body:f,message:w,timestamp:new Date().toISOString()}}_getHeaderValue(e,t){if(!e||typeof e.getHeader!="function")return"";try{const i=e.getHeader(t);return i?String(i).trim():""}catch{return""}}async _normalizeMediaAccessError(e,t="call"){return ze(e,t)}_createInviteRequestDelegate(e){const t=(s,...r)=>{if(typeof s=="function")try{s(...r)}catch(n){console.warn("SIP 邀请回调执行异常",n)}},i=e?.requestDelegate||{};return{requestDelegate:{onAccept:(...s)=>{this.lastFailureMeta=null,t(i.onAccept,...s)},onRedirect:(s,...r)=>{this._handleInviteFailure("redirect",s),t(i.onRedirect,s,...r)},onReject:(s,...r)=>{this._handleInviteFailure("reject",s),t(i.onReject,s,...r)},onProgress:(s,...r)=>{this._handleInviteProgress(s),t(i.onProgress,s,...r)},onTrying:(...s)=>{t(i.onTrying,...s)}}}}async answer(e){if(!this.simpleUser)throw new Error("呼叫客户端未初始化");try{await this._preflightAudioAccess("answer"),this._stopIncomingTone(),this._stopRingback(),await this.simpleUser.answer(e),this._scheduleLocalMonitor()}catch(t){const i=await this._normalizeMediaAccessError(t,"answer");throw this.onError&&this.onError(i),i}}async decline(){if(!this.simpleUser){this._stopAllAudioMonitors(),this._reportAudioSilence(),this._stopRingback(),this._stopIncomingTone();return}let e=null;try{await this.simpleUser.decline()}catch(t){e=t,this.onError&&this.onError(t)}finally{this._stopAllAudioMonitors(),this._reportAudioSilence(),this._stopRingback(),this._stopIncomingTone()}if(e)throw e}async hangup(){if(!this.simpleUser){this._stopAllAudioMonitors(),this._reportAudioSilence(),this._stopRingback(),this._stopIncomingTone();return}let e=null;try{this.hangupInitiatedByLocal=!0,await this.simpleUser.hangup()}catch(t){e=t,this.onError&&this.onError(t)}finally{this._stopAllAudioMonitors(),this._reportAudioSilence(),this._stopRingback(),this._stopIncomingTone()}if(e)throw e}mute(){if(this.simpleUser)try{this.simpleUser.mute()}catch(e){throw this.onError&&this.onError(e),e}}unmute(){if(this.simpleUser)try{this.simpleUser.unmute()}catch(e){throw this.onError&&this.onError(e),e}}async hold(){if(this.simpleUser)try{await this.simpleUser.hold()}catch(e){throw this.onError&&this.onError(e),e}}async unhold(){if(this.simpleUser)try{await this.simpleUser.unhold()}catch(e){throw this.onError&&this.onError(e),e}}async destroy(){this._rejectConnectionWaiters(Ke("SIP 客户端已销毁,已取消连接等待。")),this._rejectRegistrationWaiters(Ke("SIP 客户端已销毁,已取消注册等待。")),this.ensureReadyPromise=null;const e=this.simpleUser;if(e)try{this.registered&&await e.unregister(),this.connected&&await e.disconnect()}catch(t){this.onError&&this.onError(t)}this._stopAllAudioMonitors(),this._closeAudioContext(),this._stopRingback(),this._stopIncomingTone(),this._clearAutoplayUnlockTasks(),this.simpleUser=null,this.connected=!1,this.registered=!1,this.active=!1,this.account=null,this.audioTrackMeta={local:null,remote:null},this.peerConnectionDebug={attached:!1,events:[],iceCandidates:[],iceCandidateErrors:[]}}_scheduleLocalMonitor(e=0){if(!this.onAudioLevel)return;const t=this.simpleUser?.localMediaStream;if(t instanceof MediaStream&&t.getAudioTracks().length>0){this._startAudioLevelMonitor("local",t);return}e>10||setTimeout(()=>this._scheduleLocalMonitor(e+1),200*(e+1))}_scheduleRemoteMonitor(e=0){if(!this.onAudioLevel||!this.simpleUser)return;const t=this.simpleUser.remoteMediaStream||this._getRemoteAudioElement()?.srcObject;if(t instanceof MediaStream&&t.getAudioTracks&&t.getAudioTracks().length>0){this._startAudioLevelMonitor("remote",t);return}e>10||setTimeout(()=>this._scheduleRemoteMonitor(e+1),300*(e+1))}_startAudioLevelMonitor(e,t){if(!(!this.onAudioLevel&&!this.onAudioFrame)&&t instanceof MediaStream&&!(t.getAudioTracks&&t.getAudioTracks().length===0)&&this._ensureAudioContext()){try{if(t.getAudioTracks&&typeof t.getAudioTracks=="function"){const[i]=t.getAudioTracks();if(i){const s={track_id:i.id||null,label:i.label||null};try{s.settings=i.getSettings?i.getSettings():void 0}catch{s.settings=void 0}try{s.constraints=i.getConstraints?i.getConstraints():void 0}catch{s.constraints=void 0}this.audioTrackMeta=this.audioTrackMeta||{},this.audioTrackMeta[e]=s}}}catch{}this._stopAudioLevelMonitor(e);try{const i=this.audioContext.createMediaStreamSource(t),s=this.audioContext.createAnalyser();s.fftSize=2048;const r=new Uint8Array(s.fftSize);i.connect(s);const n=typeof this.onAudioFrame=="function",a=()=>{s.getByteTimeDomainData(r);let f=0;const h=n?new Float32Array(r.length):null;for(let I=0;I<r.length;I+=1){const E=(r[I]-128)/128;f+=E*E,h&&(h[I]=E)}const w=Math.sqrt(f/r.length),S=Math.min(1,w*2);if(this.onAudioLevel&&this.onAudioLevel(e,S),h&&this.audioContext&&this.onAudioFrame)try{this.onAudioFrame(e,{samples:h,sampleRate:this.audioContext.sampleRate||48e3,timestamp:Date.now()})}catch{}const x=this.audioMonitors[e];x&&(x.rafId=window.requestAnimationFrame(a))},d={source:i,analyser:s,dataArray:r,rafId:window.requestAnimationFrame(a)};this.audioMonitors[e]=d}catch(i){this.onError&&this.onError(i)}}}_stopAudioLevelMonitor(e){const t=this.audioMonitors[e];if(t){t.rafId&&window.cancelAnimationFrame(t.rafId);try{t.source&&t.source.disconnect()}catch{}delete this.audioMonitors[e]}}_stopAllAudioMonitors(){this._stopAudioLevelMonitor("local"),this._stopAudioLevelMonitor("remote"),!this.audioMonitors.local&&!this.audioMonitors.remote&&this._closeAudioContext()}_resolveToneUrl(e){return e?e.startsWith("http://")||e.startsWith("https://")||e.startsWith("/")?e:`/assets/${e}`:null}_normalizeAudioUrl(e){if(!e)return"";if(typeof window>"u")return e;try{const t=window.location?.origin||window.location?.href;return t?new URL(e,t).href:e}catch{return e}}_getAudioSourceMeta(e){return e?e._sipToneSrc?e._sipToneSrc:e.dataset&&e.dataset.sipToneSrc?e.dataset.sipToneSrc:this._normalizeAudioUrl(e.src||""):""}_markAudioSourceMeta(e,t){e&&(e.dataset&&(e.dataset.sipToneSrc=t),e._sipToneSrc=t)}_loadAudio(e,t){if(!e||typeof window>"u")return null;const i=this._normalizeAudioUrl(e);if(t){if(this._getAudioSourceMeta(t)===i)return t;try{t.pause(),t.currentTime=0}catch(r){console.warn("停止旧音频失败:",r)}}try{const s=new Audio(i);return s.loop=!0,s.preload="auto",s.volume=.6,s.playsInline=!0,s.autoplay=!0,this._markAudioSourceMeta(s,i),s}catch(s){return console.warn("创建音频失败:",s),null}}_shouldUnlock(e){if(!e)return!1;const t=e.name||e.code||"";return t==="NotAllowedError"||t==="SecurityError"}_attemptPlayAudio(e,{onSuccess:t,onError:i,unlockKey:s}){if(!e)return!1;this._ensureAudioContext();const r=()=>{typeof t=="function"&&t(),s&&this._removePendingPlaybackTask(s)},n=a=>{if(this._shouldUnlock(a)&&s){this._requestAutoplayUnlock(s,()=>{this._attemptPlayAudio(e,{onSuccess:t,onError:i,unlockKey:s})});return}typeof i=="function"&&i(a)};try{const a=e.play();a&&typeof a.then=="function"?a.then(()=>r()).catch(d=>n(d)):r()}catch(a){n(a)}return!0}_requestAutoplayUnlock(e,t){!e||typeof t!="function"||(this.pendingPlaybackTasks instanceof Map||(this.pendingPlaybackTasks=new Map),this.pendingPlaybackTasks.has(e)||this.pendingPlaybackTasks.set(e,t),!this.audioUnlockHandler&&typeof document<"u"&&(this.audioUnlockHandler=()=>{this._flushAutoplayTasks()},document.addEventListener("click",this.audioUnlockHandler,!0),document.addEventListener("touchstart",this.audioUnlockHandler,!0),document.addEventListener("keydown",this.audioUnlockHandler,!0)))}_flushAutoplayTasks(){if(!(this.pendingPlaybackTasks instanceof Map)||this.pendingPlaybackTasks.size===0){this._removeAudioUnlockHandler();return}const e=Array.from(this.pendingPlaybackTasks.entries());this.pendingPlaybackTasks.clear(),e.forEach(([t,i])=>{try{i()}catch(s){console.warn("触发音频播放失败:",s),this.pendingPlaybackTasks instanceof Map&&this.pendingPlaybackTasks.set(t,i)}}),(!(this.pendingPlaybackTasks instanceof Map)||this.pendingPlaybackTasks.size===0)&&this._removeAudioUnlockHandler()}_removeAudioUnlockHandler(){!this.audioUnlockHandler||typeof document>"u"||(document.removeEventListener("click",this.audioUnlockHandler,!0),document.removeEventListener("touchstart",this.audioUnlockHandler,!0),document.removeEventListener("keydown",this.audioUnlockHandler,!0),this.audioUnlockHandler=null)}_removePendingPlaybackTask(e){this.pendingPlaybackTasks instanceof Map&&(this.pendingPlaybackTasks.delete(e),this.pendingPlaybackTasks.size===0&&this._removeAudioUnlockHandler())}_clearAutoplayUnlockTasks(){this.pendingPlaybackTasks instanceof Map&&this.pendingPlaybackTasks.clear(),this._removeAudioUnlockHandler()}_playRingback(){this.ringbackPlaying||(this.ringbackAudio=this._loadAudio(this.ringbackToneUrl,this.ringbackAudio),this.ringbackAudio&&this._attemptPlayAudio(this.ringbackAudio,{unlockKey:"ringback",onSuccess:()=>{this.ringbackPlaying=!0},onError:e=>{this.ringbackPlaying=!1,console.warn("播放回铃音异常:",e)}}))}_stopRingback(){if(this.ringbackAudio){try{this.ringbackAudio.pause(),this.ringbackAudio.currentTime=0}catch(e){console.warn("停止回铃音异常:",e)}this.ringbackPlaying=!1,this._removePendingPlaybackTask("ringback")}}_playIncomingTone(){this.incomingPlaying||(this.incomingAudio=this._loadAudio(this.incomingToneUrl,this.incomingAudio),this.incomingAudio&&this._attemptPlayAudio(this.incomingAudio,{unlockKey:"incoming",onSuccess:()=>{this.incomingPlaying=!0},onError:e=>{this.incomingPlaying=!1,console.warn("播放振铃音异常:",e)}}))}_stopIncomingTone(){if(this.incomingAudio){try{this.incomingAudio.pause(),this.incomingAudio.currentTime=0}catch(e){console.warn("停止振铃音异常:",e)}this.incomingPlaying=!1,this._removePendingPlaybackTask("incoming")}}updateToneOptions({ringbackTone:e,incomingTone:t}){if(e){const i=this._resolveToneUrl(e);i&&i!==this.ringbackToneUrl&&(this._stopRingback(),this.ringbackToneUrl=i,this.ringbackAudio=null)}if(t){const i=this._resolveToneUrl(t);i&&i!==this.incomingToneUrl&&(this._stopIncomingTone(),this.incomingToneUrl=i,this.incomingAudio=null)}}silenceIncomingTone(){this._stopIncomingTone()}_reportAudioSilence(){this.onAudioLevel&&(this.onAudioLevel("local",0),this.onAudioLevel("remote",0))}_ensureAudioContext(){if(typeof window>"u"||!window.AudioContext&&!window.webkitAudioContext)return!1;if(!this.audioContext){const e=window.AudioContext||window.webkitAudioContext;this.audioContext=new e}return this.audioContext.state==="suspended"&&this.audioContext.resume().catch(()=>{}),!0}_closeAudioContext(){if(this.audioContext)try{this.audioContext.close()}catch{}this.audioContext=null}}const Si=/^[a-z][a-z0-9+.-]*:\/\//i;function Ti(o,e=""){const t=String(o||e||"").trim();if(!t)throw new Error("缺少统一服务基址");return t}function wt(o,e="https://"){return Si.test(o)?o:`${e}${o.replace(/^\/+/,"")}`}function Ye(o="/"){return o.endsWith("/")?o:`${o}/`}function yt(o="/",e=""){const t=Ye(o||"/"),i=String(e||"").replace(/^\/+/,"");return i?`${t}${i}`:t}function ye(o=""){return String(o||"").replace(/^\/+/,"")}function bt(o=""){const e=String(o||""),t=e.indexOf("?");return t<0?{pathname:ye(e),search:""}:{pathname:ye(e.slice(0,t)),search:e.slice(t)}}function Ci(o="/",e="/"){const t=String(o||"/"),i=Ye(e||"/");return i!=="/"&&t.startsWith(i)?ye(t.slice(i.length)):ye(t)}function _e(o,e=""){const t=wt(Ti(o,e)),i=new URL(t);return i.search="",i.hash="",i.pathname=Ye(i.pathname||"/"),i}function Ei(o,e=""){return _e(o,e).pathname!=="/"}function X(o,e,t=""){const i=_e(o,t),s=bt(e);return i.pathname=yt(i.pathname,s.pathname),i.search=s.search,i.href}function Je(o,e="ws",t=""){const i=_e(o,t);i.protocol==="https:"?i.protocol="wss:":i.protocol==="http:"?i.protocol="ws:":i.protocol!=="ws:"&&i.protocol!=="wss:"&&(i.protocol="wss:");const s=bt(e);return i.pathname=yt(i.pathname,s.pathname),i.search=s.search,i.href}function vt(o,e="",t=""){if(!String(o||"").trim())return ye(e);const i=new URL(wt(String(o).trim())),s=String(t||"").trim()?_e(t).pathname:"/",r=Ci(i.pathname||"/",s),n=String(i.search||"");return`${r}${n}`||ye(e)}function St({apiBaseUrl:o,transportBaseUrl:e="",transportUrl:t="",fallbackPath:i="ws"}){const s=String(e||"").trim();return s?Je(s,vt(t,i,s)):Ei(o)?Je(o,vt(t,i,o)):String(t||"").trim()?String(t).trim():Je(o,i)}const _i=`
|
|
63
|
+
`))}startSendingKeepAlives(){const e=t=>{const i=t*.8;return 1e3*(Math.random()*(t-i)+i)};this.configuration.keepAliveInterval&&!this.keepAliveInterval&&(this.keepAliveInterval=setInterval(()=>{this.sendKeepAlive(),this.startSendingKeepAlives()},e(this.configuration.keepAliveInterval)))}stopSendingKeepAlives(){this.keepAliveInterval&&clearInterval(this.keepAliveInterval),this.keepAliveDebounceTimeout&&clearTimeout(this.keepAliveDebounceTimeout),this.keepAliveInterval=void 0,this.keepAliveDebounceTimeout=void 0}}xe.defaultOptions={server:"",connectionTimeout:5,keepAliveInterval:0,keepAliveDebounce:10,traceSip:!0};class K{constructor(e={}){if(this._publishers={},this._registerers={},this._sessions={},this._subscriptions={},this._state=k.Stopped,this._stateEventEmitter=new Te,this.delegate=e.delegate,this.options=Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},K.defaultOptions()),{sipjsId:ue(5)}),{uri:new z("sip","anonymous."+ue(6),"anonymous.invalid")}),{viaHost:ue(12)+".invalid"}),K.stripUndefinedProperties(e)),this.options.hackIpInContact)if(typeof this.options.hackIpInContact=="boolean"&&this.options.hackIpInContact){const s=Math.floor(Math.random()*254+1);this.options.viaHost="192.0.2."+s}else this.options.hackIpInContact&&(this.options.viaHost=this.options.hackIpInContact);switch(this.loggerFactory=new Wt,this.logger=this.loggerFactory.getLogger("sip.UserAgent"),this.loggerFactory.builtinEnabled=this.options.logBuiltinEnabled,this.loggerFactory.connector=this.options.logConnector,this.options.logLevel){case"error":this.loggerFactory.level=q.error;break;case"warn":this.loggerFactory.level=q.warn;break;case"log":this.loggerFactory.level=q.log;break;case"debug":this.loggerFactory.level=q.debug;break}if(this.options.logConfiguration&&(this.logger.log("Configuration:"),Object.keys(this.options).forEach(t=>{const i=this.options[t];switch(t){case"uri":case"sessionDescriptionHandlerFactory":this.logger.log("· "+t+": "+i);break;case"authorizationPassword":this.logger.log("· "+t+": NOT SHOWN");break;case"transportConstructor":this.logger.log("· "+t+": "+i.name);break;default:this.logger.log("· "+t+": "+JSON.stringify(i))}})),this.options.transportOptions){const t=this.options.transportOptions,i=t.maxReconnectionAttempts,s=t.reconnectionTimeout;i!==void 0&&this.logger.warn('The transport option "maxReconnectionAttempts" as has apparently been specified and has been deprecated. It will no longer be available starting with SIP.js release 0.16.0. Please update accordingly.'),s!==void 0&&this.logger.warn('The transport option "reconnectionTimeout" as has apparently been specified and has been deprecated. It will no longer be available starting with SIP.js release 0.16.0. Please update accordingly.'),e.reconnectionDelay===void 0&&s!==void 0&&(this.options.reconnectionDelay=s),e.reconnectionAttempts===void 0&&i!==void 0&&(this.options.reconnectionAttempts=i)}if(e.reconnectionDelay!==void 0&&this.logger.warn('The user agent option "reconnectionDelay" as has apparently been specified and has been deprecated. It will no longer be available starting with SIP.js release 0.16.0. Please update accordingly.'),e.reconnectionAttempts!==void 0&&this.logger.warn('The user agent option "reconnectionAttempts" as has apparently been specified and has been deprecated. It will no longer be available starting with SIP.js release 0.16.0. Please update accordingly.'),this._transport=new this.options.transportConstructor(this.getLogger("sip.Transport"),this.options.transportOptions),this.initTransportCallbacks(),this._contact=this.initContact(),this._instanceId=this.options.instanceId?this.options.instanceId:K.newUUID(),P.parse(this._instanceId,"uuid")===-1)throw new Error("Invalid instanceId.");this._userAgentCore=this.initCore()}static makeURI(e){return P.URIParse(e)}static defaultOptions(){return{allowLegacyNotifications:!1,authorizationHa1:"",authorizationPassword:"",authorizationUsername:"",delegate:{},contactName:"",contactParams:{transport:"ws"},displayName:"",forceRport:!1,gracefulShutdown:!0,hackAllowUnregisteredOptionTags:!1,hackIpInContact:!1,hackViaTcp:!1,instanceId:"",instanceIdAlwaysAdded:!1,logBuiltinEnabled:!0,logConfiguration:!0,logConnector:()=>{},logLevel:"log",noAnswerTimeout:60,preloadedRouteSet:[],reconnectionAttempts:0,reconnectionDelay:4,sendInitialProvisionalResponse:!0,sessionDescriptionHandlerFactory:pi(),sessionDescriptionHandlerFactoryOptions:{},sipExtension100rel:W.Unsupported,sipExtensionReplaces:W.Unsupported,sipExtensionExtraSupported:[],sipjsId:"",transportConstructor:xe,transportOptions:{},uri:new z("sip","anonymous","anonymous.invalid"),userAgentString:"SIP.js/"+Pt,viaHost:""}}static newUUID(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{const i=Math.floor(Math.random()*16);return(t==="x"?i:i%4+8).toString(16)})}static stripUndefinedProperties(e){return Object.keys(e).reduce((t,i)=>(e[i]!==void 0&&(t[i]=e[i]),t),{})}get configuration(){return this.options}get contact(){return this._contact}get instanceId(){return this._instanceId}get state(){return this._state}get stateChange(){return this._stateEventEmitter}get transport(){return this._transport}get userAgentCore(){return this._userAgentCore}getLogger(e,t){return this.loggerFactory.getLogger(e,t)}getLoggerFactory(){return this.loggerFactory}isConnected(){return this.transport.isConnected()}reconnect(){return this.state===k.Stopped?Promise.reject(new Error("User agent stopped.")):Promise.resolve().then(()=>this.transport.connect())}start(){return this.state===k.Started?(this.logger.warn("User agent already started"),Promise.resolve()):(this.logger.log(`Starting ${this.configuration.uri}`),this.transitionState(k.Started),this.transport.connect())}async stop(){if(this.state===k.Stopped)return this.logger.warn("User agent already stopped"),Promise.resolve();if(this.logger.log(`Stopping ${this.configuration.uri}`),!this.options.gracefulShutdown)return this.logger.log("Dispose of transport"),this.transport.dispose().catch(o=>{throw this.logger.error(o.message),o}),this.logger.log("Dispose of core"),this.userAgentCore.dispose(),this._publishers={},this._registerers={},this._sessions={},this._subscriptions={},this.transitionState(k.Stopped),Promise.resolve();const e=Object.assign({},this._publishers),t=Object.assign({},this._registerers),i=Object.assign({},this._sessions),s=Object.assign({},this._subscriptions),r=this.transport,n=this.userAgentCore;this.logger.log("Dispose of registerers");for(const o in t)t[o]&&await t[o].dispose().catch(d=>{throw this.logger.error(d.message),delete this._registerers[o],d});this.logger.log("Dispose of sessions");for(const o in i)i[o]&&await i[o].dispose().catch(d=>{throw this.logger.error(d.message),delete this._sessions[o],d});this.logger.log("Dispose of subscriptions");for(const o in s)s[o]&&await s[o].dispose().catch(d=>{throw this.logger.error(d.message),delete this._subscriptions[o],d});this.logger.log("Dispose of publishers");for(const o in e)e[o]&&await e[o].dispose().catch(d=>{throw this.logger.error(d.message),delete this._publishers[o],d});this.logger.log("Dispose of transport"),await r.dispose().catch(o=>{throw this.logger.error(o.message),o}),this.logger.log("Dispose of core"),n.dispose(),this.transitionState(k.Stopped)}_makeInviter(e,t){return new Pe(this,e,t)}attemptReconnection(e=1){const t=this.options.reconnectionAttempts,i=this.options.reconnectionDelay;if(e>t){this.logger.log("Maximum reconnection attempts reached");return}this.logger.log(`Reconnection attempt ${e} of ${t} - trying`),setTimeout(()=>{this.reconnect().then(()=>{this.logger.log(`Reconnection attempt ${e} of ${t} - succeeded`)}).catch(s=>{this.logger.error(s.message),this.logger.log(`Reconnection attempt ${e} of ${t} - failed`),this.attemptReconnection(++e)})},e===1?0:i*1e3)}initContact(){const e=this.options.contactName!==""?this.options.contactName:ue(8),t=this.options.contactParams;return{pubGruu:void 0,tempGruu:void 0,uri:new z("sip",e,this.options.viaHost,void 0,t),toString:(s={})=>{const r=s.anonymous||!1,n=s.outbound||!1,o=s.register||!1;let d="<";return r?d+=this.contact.tempGruu||`sip:anonymous@anonymous.invalid;transport=${t.transport?t.transport:"ws"}`:o?d+=this.contact.uri:d+=this.contact.pubGruu||this.contact.uri,n&&(d+=";ob"),d+=">",this.options.instanceIdAlwaysAdded&&(d+=';+sip.instance="<urn:uuid:'+this._instanceId+'>"'),d}}}initCore(){let e=[];e.push("outbound"),this.options.sipExtension100rel===W.Supported&&e.push("100rel"),this.options.sipExtensionReplaces===W.Supported&&e.push("replaces"),this.options.sipExtensionExtraSupported&&e.push(...this.options.sipExtensionExtraSupported),this.options.hackAllowUnregisteredOptionTags||(e=e.filter(r=>jt[r])),e=Array.from(new Set(e));const t=e.slice();(this.contact.pubGruu||this.contact.tempGruu)&&t.push("gruu");const i={aor:this.options.uri,contact:this.contact,displayName:this.options.displayName,loggerFactory:this.loggerFactory,hackViaTcp:this.options.hackViaTcp,routeSet:this.options.preloadedRouteSet,supportedOptionTags:e,supportedOptionTagsResponse:t,sipjsId:this.options.sipjsId,userAgentHeaderFieldValue:this.options.userAgentString,viaForceRport:this.options.forceRport,viaHost:this.options.viaHost,authenticationFactory:()=>{const r=this.options.authorizationUsername?this.options.authorizationUsername:this.options.uri.user,n=this.options.authorizationPassword?this.options.authorizationPassword:void 0,o=this.options.authorizationHa1?this.options.authorizationHa1:void 0;return new Gt(this.getLoggerFactory(),o,r,n)},transportAccessor:()=>this.transport},s={onInvite:r=>{var n;const o=new fe(this,r);if(r.delegate={onCancel:d=>{o._onCancel(d)},onTransportError:d=>{this.logger.error("A transport error has occurred while handling an incoming INVITE request.")}},r.trying(),this.options.sipExtensionReplaces!==W.Unsupported){const u=r.message.parseHeader("replaces");if(u){const h=u.call_id;if(typeof h!="string")throw new Error("Type of call id is not string");const m=u.replaces_to_tag;if(typeof m!="string")throw new Error("Type of to tag is not string");const S=u.replaces_from_tag;if(typeof S!="string")throw new Error("type of from tag is not string");const x=h+m+S,_=this.userAgentCore.dialogs.get(x);if(!_){o.reject({statusCode:481});return}if(!_.early&&u.early_only===!0){o.reject({statusCode:486});return}const C=this._sessions[h+S]||this._sessions[h+m]||void 0;if(!C)throw new Error("Session does not exist.");o._replacee=C}}if(!((n=this.delegate)===null||n===void 0)&&n.onInvite){if(o.autoSendAnInitialProvisionalResponse){o.progress().then(()=>{var d;if(((d=this.delegate)===null||d===void 0?void 0:d.onInvite)===void 0)throw new Error("onInvite undefined.");this.delegate.onInvite(o)});return}this.delegate.onInvite(o);return}o.reject({statusCode:486})},onMessage:r=>{if(this.delegate&&this.delegate.onMessage){const n=new ct(r);this.delegate.onMessage(n)}else r.accept()},onNotify:r=>{if(this.delegate&&this.delegate.onNotify){const n=new Be(r);this.delegate.onNotify(n)}else this.options.allowLegacyNotifications?r.accept():r.reject({statusCode:481})},onRefer:r=>{this.logger.warn("Received an out of dialog REFER request"),this.delegate&&this.delegate.onReferRequest?this.delegate.onReferRequest(r):r.reject({statusCode:405})},onRegister:r=>{this.logger.warn("Received an out of dialog REGISTER request"),this.delegate&&this.delegate.onRegisterRequest?this.delegate.onRegisterRequest(r):r.reject({statusCode:405})},onSubscribe:r=>{this.logger.warn("Received an out of dialog SUBSCRIBE request"),this.delegate&&this.delegate.onSubscribeRequest?this.delegate.onSubscribeRequest(r):r.reject({statusCode:405})}};return new ui(i,s)}initTransportCallbacks(){this.transport.onConnect=()=>this.onTransportConnect(),this.transport.onDisconnect=e=>this.onTransportDisconnect(e),this.transport.onMessage=e=>this.onTransportMessage(e)}onTransportConnect(){this.state!==k.Stopped&&this.delegate&&this.delegate.onConnect&&this.delegate.onConnect()}onTransportDisconnect(e){this.state!==k.Stopped&&(this.delegate&&this.delegate.onDisconnect&&this.delegate.onDisconnect(e),e&&this.options.reconnectionAttempts>0&&this.attemptReconnection())}onTransportMessage(e){const t=ke.parseMessage(e,this.getLogger("sip.Parser"));if(!t){this.logger.warn("Failed to parse incoming message. Dropping.");return}if(this.state===k.Stopped&&t instanceof me){this.logger.warn(`Received ${t.method} request while stopped. Dropping.`);return}const i=()=>{const s=["from","to","call_id","cseq","via"];for(const r of s)if(!t.hasHeader(r))return this.logger.warn(`Missing mandatory header field : ${r}.`),!1;return!0};if(t instanceof me){if(!i()){this.logger.warn("Request missing mandatory header field. Dropping.");return}if(!t.toTag&&t.callId.substr(0,5)===this.options.sipjsId){this.userAgentCore.replyStateless(t,{statusCode:482});return}const s=Ce(t.body),r=t.getHeader("content-length");if(r&&s<Number(r)){this.userAgentCore.replyStateless(t,{statusCode:400});return}}if(t instanceof re){if(!i()){this.logger.warn("Response missing mandatory header field. Dropping.");return}if(t.getHeaders("via").length>1){this.logger.warn("More than one Via header field present in the response. Dropping.");return}if(t.via.host!==this.options.viaHost||t.via.port!==void 0){this.logger.warn("Via sent-by in the response does not match UA Via host value. Dropping.");return}const s=Ce(t.body),r=t.getHeader("content-length");if(r&&s<Number(r)){this.logger.warn("Message body length is lower than the value in Content-Length header field. Dropping.");return}}if(t instanceof me){this.userAgentCore.receiveIncomingRequestFromTransport(t);return}if(t instanceof re){this.userAgentCore.receiveIncomingResponseFromTransport(t);return}throw new Error("Invalid message type.")}transitionState(e,t){const i=()=>{throw new Error(`Invalid state transition from ${this._state} to ${e}`)};switch(this._state){case k.Started:e!==k.Stopped&&i();break;case k.Stopped:e!==k.Started&&i();break;default:throw new Error("Unknown state.")}this.logger.log(`Transitioned from ${this._state} to ${e}`),this._state=e,this._stateEventEmitter.emit(this._state)}}function mi(){return(a,e)=>({session:e,held:!1,muted:!1})}class Ge{constructor(e,t={}){this.managedSessions=[],this.attemptingReconnection=!1,this.optionsPingFailure=!1,this.optionsPingRunning=!1,this.shouldBeConnected=!1,this.shouldBeRegistered=!1,this.delegate=t.delegate,this.options=Object.assign({aor:"",autoStop:!0,delegate:{},iceStopWaitingOnServerReflexive:!1,managedSessionFactory:mi(),maxSimultaneousSessions:2,media:{},optionsPingInterval:-1,optionsPingRequestURI:"",reconnectionAttempts:3,reconnectionDelay:4,registrationRetry:!1,registrationRetryInterval:3,registerGuard:null,registererOptions:{},registererRegisterOptions:{},sendDTMFUsingSessionDescriptionHandler:!1,userAgentOptions:{}},Ge.stripUndefinedProperties(t));const i=Object.assign({},t.userAgentOptions);if(i.transportConstructor||(i.transportConstructor=xe),i.transportOptions||(i.transportOptions={server:e}),!i.uri&&t.aor){const s=K.makeURI(t.aor);if(!s)throw new Error(`Failed to create valid URI from ${t.aor}`);i.uri=s}if(this.userAgent=new K(i),this.userAgent.delegate={onConnect:()=>{this.logger.log("Connected"),this.delegate&&this.delegate.onServerConnect&&this.delegate.onServerConnect(),this.shouldBeRegistered&&this.register(),this.options.optionsPingInterval>0&&this.optionsPingStart()},onDisconnect:async s=>{this.logger.log("Disconnected");let r=!1;this.options.optionsPingInterval>0&&(r=this.optionsPingFailure,this.optionsPingFailure=!1,this.optionsPingStop()),this.delegate&&this.delegate.onServerDisconnect&&this.delegate.onServerDisconnect(s),(s||r)&&(this.registerer&&(this.logger.log("Disposing of registerer..."),this.registerer.dispose().catch(n=>{this.logger.debug("Error occurred disposing of registerer after connection with server was lost."),this.logger.debug(n.toString())}),this.registerer=void 0),this.managedSessions.slice().map(n=>n.session).forEach(async n=>{this.logger.log("Disposing of session..."),n.dispose().catch(o=>{this.logger.debug("Error occurred disposing of a session after connection with server was lost."),this.logger.debug(o.toString())})}),this.shouldBeConnected&&this.attemptReconnection())},onInvite:s=>{this.logger.log(`[${s.id}] Received INVITE`);const r=this.options.maxSimultaneousSessions;if(r!==0&&this.managedSessions.length>r){this.logger.warn(`[${s.id}] Session already in progress, rejecting INVITE...`),s.reject().then(()=>{this.logger.log(`[${s.id}] Rejected INVITE`)}).catch(o=>{this.logger.error(`[${s.id}] Failed to reject INVITE`),this.logger.error(o.toString())});return}const n={sessionDescriptionHandlerOptions:{constraints:this.constraints}};this.initSession(s,n),this.delegate&&this.delegate.onCallReceived?this.delegate.onCallReceived(s):(this.logger.warn(`[${s.id}] No handler available, rejecting INVITE...`),s.reject().then(()=>{this.logger.log(`[${s.id}] Rejected INVITE`)}).catch(o=>{this.logger.error(`[${s.id}] Failed to reject INVITE`),this.logger.error(o.toString())}))},onMessage:s=>{s.accept().then(()=>{this.delegate&&this.delegate.onMessageReceived&&this.delegate.onMessageReceived(s)})},onNotify:s=>{s.accept().then(()=>{this.delegate&&this.delegate.onNotificationReceived&&this.delegate.onNotificationReceived(s)})}},this.registererOptions=Object.assign({},t.registererOptions),this.registererRegisterOptions=Object.assign({},t.registererRegisterOptions),this.options.registrationRetry){this.registererRegisterOptions.requestDelegate=this.registererRegisterOptions.requestDelegate||{};const s=this.registererRegisterOptions.requestDelegate.onReject;this.registererRegisterOptions.requestDelegate.onReject=r=>{s&&s(r),this.attemptRegistration()}}this.logger=this.userAgent.getLogger("sip.SessionManager"),window.addEventListener("online",()=>{this.logger.log("Online"),this.shouldBeConnected&&this.connect()}),this.options.autoStop&&window.addEventListener("beforeunload",async()=>{this.shouldBeConnected=!1,this.shouldBeRegistered=!1,this.userAgent.state!==k.Stopped&&await this.userAgent.stop()})}static stripUndefinedProperties(e){return Object.keys(e).reduce((t,i)=>(e[i]!==void 0&&(t[i]=e[i]),t),{})}getLocalMediaStream(e){const t=e.sessionDescriptionHandler;if(t){if(!(t instanceof F))throw new Error("Session description handler not instance of web SessionDescriptionHandler");return t.localMediaStream}}getRemoteMediaStream(e){const t=e.sessionDescriptionHandler;if(t){if(!(t instanceof F))throw new Error("Session description handler not instance of web SessionDescriptionHandler");return t.remoteMediaStream}}getLocalAudioTrack(e){var t;return(t=this.getLocalMediaStream(e))===null||t===void 0?void 0:t.getTracks().find(i=>i.kind==="audio")}getLocalVideoTrack(e){var t;return(t=this.getLocalMediaStream(e))===null||t===void 0?void 0:t.getTracks().find(i=>i.kind==="video")}getRemoteAudioTrack(e){var t;return(t=this.getRemoteMediaStream(e))===null||t===void 0?void 0:t.getTracks().find(i=>i.kind==="audio")}getRemoteVideoTrack(e){var t;return(t=this.getRemoteMediaStream(e))===null||t===void 0?void 0:t.getTracks().find(i=>i.kind==="video")}async connect(){return this.logger.log("Connecting UserAgent..."),this.shouldBeConnected=!0,this.userAgent.state!==k.Started?this.userAgent.start():this.userAgent.reconnect()}async disconnect(){return this.logger.log("Disconnecting UserAgent..."),this.userAgent.state===k.Stopped?Promise.resolve():(this.shouldBeConnected=!1,this.shouldBeRegistered=!1,this.registerer=void 0,this.userAgent.stop())}isConnected(){return this.userAgent.isConnected()}async register(e){return this.logger.log("Registering UserAgent..."),this.shouldBeRegistered=!0,e!==void 0&&(this.registererRegisterOptions=Object.assign({},e)),this.registerer||(this.registerer=new J(this.userAgent,this.registererOptions),this.registerer.stateChange.addListener(t=>{switch(t){case R.Initial:break;case R.Registered:this.delegate&&this.delegate.onRegistered&&this.delegate.onRegistered();break;case R.Unregistered:this.delegate&&this.delegate.onUnregistered&&this.delegate.onUnregistered(),this.shouldBeRegistered&&this.attemptRegistration();break;case R.Terminated:break;default:throw new Error("Unknown registerer state.")}})),this.attemptRegistration(!0)}async unregister(e){return this.logger.log("Unregistering UserAgent..."),this.shouldBeRegistered=!1,this.registerer?this.registerer.unregister(e).then(()=>{}):(this.logger.warn("No registerer to unregister."),Promise.resolve())}async call(e,t,i){this.logger.log("Beginning Session...");const s=this.options.maxSimultaneousSessions;if(s!==0&&this.managedSessions.length>s)return Promise.reject(new Error("Maximum number of sessions already exists."));const r=K.makeURI(e);if(!r)return Promise.reject(new Error(`Failed to create a valid URI from "${e}"`));if(t||(t={}),t.sessionDescriptionHandlerOptions||(t.sessionDescriptionHandlerOptions={}),t.sessionDescriptionHandlerOptions.constraints||(t.sessionDescriptionHandlerOptions.constraints=this.constraints),t.earlyMedia){i=i||{},i.requestDelegate=i.requestDelegate||{};const o=i.requestDelegate.onProgress;i.requestDelegate.onProgress=d=>{d.message.statusCode===183&&this.setupRemoteMedia(n),o&&o(d)}}this.options.iceStopWaitingOnServerReflexive&&(t.delegate=t.delegate||{},t.delegate.onSessionDescriptionHandler=o=>{if(!(o instanceof F))throw new Error("Session description handler not instance of SessionDescriptionHandler");o.peerConnectionDelegate={onicecandidate:d=>{var u;((u=d.candidate)===null||u===void 0?void 0:u.type)==="srflx"&&(this.logger.log(`[${n.id}] Found srflx ICE candidate, stop waiting...`),o.iceGatheringComplete())}}});const n=new Pe(this.userAgent,r,t);return this.sendInvite(n,t,i).then(()=>n)}async hangup(e){return this.logger.log(`[${e.id}] Hangup...`),this.sessionExists(e)?this.terminate(e):Promise.reject(new Error("Session does not exist."))}async answer(e,t){return this.logger.log(`[${e.id}] Accepting Invitation...`),this.sessionExists(e)?e instanceof fe?(t||(t={}),t.sessionDescriptionHandlerOptions||(t.sessionDescriptionHandlerOptions={}),t.sessionDescriptionHandlerOptions.constraints||(t.sessionDescriptionHandlerOptions.constraints=this.constraints),e.accept(t)):Promise.reject(new Error("Session not instance of Invitation.")):Promise.reject(new Error("Session does not exist."))}async decline(e){return this.logger.log(`[${e.id}] Rejecting Invitation...`),this.sessionExists(e)?e instanceof fe?e.reject():Promise.reject(new Error("Session not instance of Invitation.")):Promise.reject(new Error("Session does not exist."))}async hold(e){return this.logger.log(`[${e.id}] Holding session...`),this.setHold(e,!0)}async unhold(e){return this.logger.log(`[${e.id}] Unholding session...`),this.setHold(e,!1)}isHeld(e){const t=this.sessionManaged(e);return t?t.held:!1}mute(e){this.logger.log(`[${e.id}] Disabling media tracks...`),this.setMute(e,!0)}unmute(e){this.logger.log(`[${e.id}] Enabling media tracks...`),this.setMute(e,!1)}isMuted(e){const t=this.sessionManaged(e);return t?t.muted:!1}async sendDTMF(e,t){if(this.logger.log(`[${e.id}] Sending DTMF...`),!/^[0-9A-D#*,]$/.exec(t))return Promise.reject(new Error("Invalid DTMF tone."));if(!this.sessionExists(e))return Promise.reject(new Error("Session does not exist."));if(this.logger.log(`[${e.id}] Sending DTMF tone: ${t}`),this.options.sendDTMFUsingSessionDescriptionHandler)return e.sessionDescriptionHandler?e.sessionDescriptionHandler.sendDtmf(t)?Promise.resolve():Promise.reject(new Error("Failed to send DTMF")):Promise.reject(new Error("Session desciption handler undefined."));{const n={body:{contentDisposition:"render",contentType:"application/dtmf-relay",content:"Signal="+t+`\r
|
|
64
|
+
Duration=`+2e3}};return e.info({requestOptions:n}).then(()=>{})}}async transfer(e,t,i){if(this.logger.log(`[${e.id}] Referring session...`),t instanceof we)return e.refer(t,i).then(()=>{});const s=K.makeURI(t);return s?e.refer(s,i).then(()=>{}):Promise.reject(new Error(`Failed to create a valid URI from "${t}"`))}async message(e,t){this.logger.log("Sending message...");const i=K.makeURI(e);return i?new Vt(this.userAgent,i,t).message():Promise.reject(new Error(`Failed to create a valid URI from "${e}"`))}get constraints(){let e={audio:!0,video:!1};return this.options.media.constraints&&(e=Object.assign({},this.options.media.constraints)),e}attemptReconnection(e=1){const t=this.options.reconnectionAttempts,i=this.options.reconnectionDelay;if(!this.shouldBeConnected){this.logger.log("Should not be connected currently");return}if(this.attemptingReconnection&&this.logger.log("Reconnection attempt already in progress"),e>t){this.logger.log("Reconnection maximum attempts reached");return}e===1?this.logger.log(`Reconnection attempt ${e} of ${t} - trying`):this.logger.log(`Reconnection attempt ${e} of ${t} - trying in ${i} seconds`),this.attemptingReconnection=!0,setTimeout(()=>{if(!this.shouldBeConnected){this.logger.log(`Reconnection attempt ${e} of ${t} - aborted`),this.attemptingReconnection=!1;return}this.userAgent.reconnect().then(()=>{this.logger.log(`Reconnection attempt ${e} of ${t} - succeeded`),this.attemptingReconnection=!1}).catch(s=>{this.logger.log(`Reconnection attempt ${e} of ${t} - failed`),this.logger.error(s.message),this.attemptingReconnection=!1,this.attemptReconnection(++e)})},e===1?0:i*1e3)}attemptRegistration(e=!1){if(this.logger.log(`Registration attempt ${e?"without delay":""}`),!this.shouldBeRegistered)return this.logger.log("Should not be registered currently"),Promise.resolve();if(this.registrationAttemptTimeout!==void 0)return this.logger.log("Registration attempt already in progress"),Promise.resolve();const t=()=>this.registerer?this.isConnected()?this.userAgent.state===k.Stopped?(this.logger.log("User agent stopped"),Promise.resolve()):this.options.registerGuard?this.options.registerGuard().catch(s=>{throw this.logger.log("Register guard rejected will making registration attempt"),s}).then(s=>s||!this.registerer?Promise.resolve():this.registerer.register(this.registererRegisterOptions).then(()=>{})):this.registerer.register(this.registererRegisterOptions).then(()=>{}):(this.logger.log("User agent not connected"),Promise.resolve()):(this.logger.log("Registerer undefined"),Promise.resolve()),i=s=>{const r=s*2;return 1e3*(Math.random()*(r-s)+s)};return new Promise((s,r)=>{this.registrationAttemptTimeout=setTimeout(()=>{t().then(()=>{this.registrationAttemptTimeout=void 0,s()}).catch(n=>{this.registrationAttemptTimeout=void 0,n instanceof ve?s():r(n)})},e?0:i(this.options.registrationRetryInterval))})}cleanupMedia(e){const t=this.sessionManaged(e);if(!t)throw new Error("Managed session does not exist.");t.mediaLocal&&t.mediaLocal.video&&(t.mediaLocal.video.srcObject=null,t.mediaLocal.video.pause()),t.mediaRemote&&(t.mediaRemote.audio&&(t.mediaRemote.audio.srcObject=null,t.mediaRemote.audio.pause()),t.mediaRemote.video&&(t.mediaRemote.video.srcObject=null,t.mediaRemote.video.pause()))}enableReceiverTracks(e,t){if(!this.sessionExists(e))throw new Error("Session does not exist.");const i=e.sessionDescriptionHandler;if(!(i instanceof F))throw new Error("Session's session description handler not instance of SessionDescriptionHandler.");i.enableReceiverTracks(t)}enableSenderTracks(e,t){if(!this.sessionExists(e))throw new Error("Session does not exist.");const i=e.sessionDescriptionHandler;if(!(i instanceof F))throw new Error("Session's session description handler not instance of SessionDescriptionHandler.");i.enableSenderTracks(t)}initSession(e,t){this.sessionAdd(e),this.delegate&&this.delegate.onCallCreated&&this.delegate.onCallCreated(e),e.stateChange.addListener(i=>{switch(this.logger.log(`[${e.id}] Session state changed to ${i}`),i){case w.Initial:break;case w.Establishing:break;case w.Established:this.setupLocalMedia(e),this.setupRemoteMedia(e),this.delegate&&this.delegate.onCallAnswered&&this.delegate.onCallAnswered(e);break;case w.Terminating:case w.Terminated:this.sessionExists(e)&&(this.cleanupMedia(e),this.sessionRemove(e),this.delegate&&this.delegate.onCallHangup&&this.delegate.onCallHangup(e));break;default:throw new Error("Unknown session state.")}}),e.delegate=e.delegate||{},e.delegate.onInfo=i=>{var s;if(((s=this.delegate)===null||s===void 0?void 0:s.onCallDTMFReceived)===void 0){i.reject();return}const r=i.request.getHeader("content-type");if(!r||!/^application\/dtmf-relay/i.exec(r)){i.reject();return}const n=i.request.body.split(`\r
|
|
65
|
+
`,2);if(n.length!==2){i.reject();return}let o;const d=/^(Signal\s*?=\s*?)([0-9A-D#*]{1})(\s)?.*/;if(n[0]!==void 0&&d.test(n[0])&&(o=n[0].replace(d,"$2")),!o){i.reject();return}let u;const h=/^(Duration\s?=\s?)([0-9]{1,4})(\s)?.*/;if(n[1]!==void 0&&h.test(n[1])&&(u=parseInt(n[1].replace(h,"$2"),10)),!u){i.reject();return}i.accept().then(()=>{if(this.delegate&&this.delegate.onCallDTMFReceived){if(!o||!u)throw new Error("Tone or duration undefined.");this.delegate.onCallDTMFReceived(e,o,u)}}).catch(m=>{this.logger.error(m.message)})},e.delegate.onRefer=i=>{i.accept().then(()=>this.sendInvite(i.makeInviter(t),t)).catch(s=>{this.logger.error(s.message)})}}optionsPingRun(e,t,i){if(this.options.optionsPingInterval<1)throw new Error("Invalid options ping interval.");this.optionsPingRunning||(this.optionsPingRunning=!0,this.optionsPingTimeout=setTimeout(()=>{this.optionsPingTimeout=void 0;const s=()=>{this.optionsPingFailure=!1,this.optionsPingRunning&&(this.optionsPingRunning=!1,this.optionsPingRun(e,t,i))},r=()=>{this.logger.error("OPTIONS ping failed"),this.optionsPingFailure=!0,this.optionsPingRunning=!1,this.userAgent.transport.disconnect().catch(d=>this.logger.error(d))},n=this.userAgent.userAgentCore,o=n.makeOutgoingRequestMessage("OPTIONS",e,t,i,{});this.optionsPingRequest=n.request(o,{onAccept:()=>{this.optionsPingRequest=void 0,s()},onReject:d=>{this.optionsPingRequest=void 0,d.message.statusCode===408||d.message.statusCode===503?r():s()}})},this.options.optionsPingInterval*1e3))}optionsPingStart(){this.logger.log("OPTIONS pings started");let e,t,i;if(this.options.optionsPingRequestURI){if(e=K.makeURI(this.options.optionsPingRequestURI),!e)throw new Error("Failed to create Request URI.");t=this.userAgent.contact.uri.clone(),i=this.userAgent.contact.uri.clone()}else if(this.options.aor){const s=K.makeURI(this.options.aor);if(!s)throw new Error("Failed to create URI.");e=s.clone(),e.user=void 0,t=s.clone(),i=s.clone()}else{this.logger.error("You have enabled sending OPTIONS pings and as such you must provide either a) an AOR to register, or b) an RURI to use for the target of the OPTIONS ping requests. ");return}this.optionsPingRun(e,t,i)}optionsPingStop(){this.logger.log("OPTIONS pings stopped"),this.optionsPingRunning=!1,this.optionsPingFailure=!1,this.optionsPingRequest&&(this.optionsPingRequest.dispose(),this.optionsPingRequest=void 0),this.optionsPingTimeout&&(clearTimeout(this.optionsPingTimeout),this.optionsPingTimeout=void 0)}async sendInvite(e,t,i){return this.initSession(e,t),e.invite(i).then(()=>{this.logger.log(`[${e.id}] Sent INVITE`)})}sessionAdd(e){const t=this.options.managedSessionFactory(this,e);this.managedSessions.push(t)}sessionExists(e){return this.sessionManaged(e)!==void 0}sessionManaged(e){return this.managedSessions.find(t=>t.session.id===e.id)}sessionRemove(e){this.managedSessions=this.managedSessions.filter(t=>t.session.id!==e.id)}async setHold(e,t){if(!this.sessionExists(e))return Promise.reject(new Error("Session does not exist."));if(this.isHeld(e)===t)return Promise.resolve();if(!(e.sessionDescriptionHandler instanceof F))throw new Error("Session's session description handler not instance of SessionDescriptionHandler.");const s={requestDelegate:{onAccept:()=>{const o=this.sessionManaged(e);o!==void 0&&(o.held=t,this.enableReceiverTracks(e,!o.held),this.enableSenderTracks(e,!o.held&&!o.muted),this.delegate&&this.delegate.onCallHold&&this.delegate.onCallHold(e,o.held))},onReject:()=>{this.logger.warn(`[${e.id}] Re-invite request was rejected`);const o=this.sessionManaged(e);o!==void 0&&(o.held=!t,this.enableReceiverTracks(e,!o.held),this.enableSenderTracks(e,!o.held&&!o.muted),this.delegate&&this.delegate.onCallHold&&this.delegate.onCallHold(e,o.held))}}},r=e.sessionDescriptionHandlerOptionsReInvite;r.hold=t,e.sessionDescriptionHandlerOptionsReInvite=r;const n=this.sessionManaged(e);if(!n)throw new Error("Managed session is undefiend.");return n.held=t,e.invite(s).then(()=>{const o=this.sessionManaged(e);o!==void 0&&(this.enableReceiverTracks(e,!o.held),this.enableSenderTracks(e,!o.held&&!o.muted))}).catch(o=>{throw n.held=!t,o instanceof ve&&this.logger.error(`[${e.id}] A hold request is already in progress.`),o})}setMute(e,t){if(!this.sessionExists(e)){this.logger.warn(`[${e.id}] A session is required to enabled/disable media tracks`);return}if(e.state!==w.Established){this.logger.warn(`[${e.id}] An established session is required to enable/disable media tracks`);return}const i=this.sessionManaged(e);i!==void 0&&(i.muted=t,this.enableSenderTracks(e,!i.held&&!i.muted))}setupLocalMedia(e){const t=this.sessionManaged(e);if(!t)throw new Error("Managed session does not exist.");const i=typeof this.options.media.local=="function"?this.options.media.local(e):this.options.media.local;t.mediaLocal=i;const s=i?.video;if(s){const r=this.getLocalMediaStream(e);if(!r)throw new Error("Local media stream undefiend.");s.srcObject=r,s.volume=0,s.play().catch(n=>{this.logger.error(`[${e.id}] Failed to play local media`),this.logger.error(n.message)})}}setupRemoteMedia(e){const t=this.sessionManaged(e);if(!t)throw new Error("Managed session does not exist.");const i=typeof this.options.media.remote=="function"?this.options.media.remote(e):this.options.media.remote;t.mediaRemote=i;const s=i?.video||i?.audio;if(s){const r=this.getRemoteMediaStream(e);if(!r)throw new Error("Remote media stream undefiend.");s.autoplay=!0,s.srcObject=r,s.play().catch(n=>{this.logger.error(`[${e.id}] Failed to play remote media`),this.logger.error(n.message)}),r.onaddtrack=()=>{this.logger.log("Remote media onaddtrack"),s.load(),s.play().catch(n=>{this.logger.error(`[${e.id}] Failed to play remote media`),this.logger.error(n.message)})}}}async terminate(e){switch(this.logger.log(`[${e.id}] Terminating...`),e.state){case w.Initial:if(e instanceof Pe)return e.cancel().then(()=>{this.logger.log(`[${e.id}] Inviter never sent INVITE (canceled)`)});if(e instanceof fe)return e.reject().then(()=>{this.logger.log(`[${e.id}] Invitation rejected (sent 480)`)});throw new Error("Unknown session type.");case w.Establishing:if(e instanceof Pe)return e.cancel().then(()=>{this.logger.log(`[${e.id}] Inviter canceled (sent CANCEL)`)});if(e instanceof fe)return e.reject().then(()=>{this.logger.log(`[${e.id}] Invitation rejected (sent 480)`)});throw new Error("Unknown session type.");case w.Established:return e.bye().then(()=>{this.logger.log(`[${e.id}] Session ended (sent BYE)`)});case w.Terminating:break;case w.Terminated:break;default:throw new Error("Unknown state")}return this.logger.log(`[${e.id}] Terminating in state ${e.state}, no action taken`),Promise.resolve()}}class wi{constructor(e,t={}){this.session=void 0,this.delegate=t.delegate,this.options=Object.assign({},t);const i={aor:this.options.aor,delegate:{onCallAnswered:()=>{var s,r;return(r=(s=this.delegate)===null||s===void 0?void 0:s.onCallAnswered)===null||r===void 0?void 0:r.call(s)},onCallCreated:s=>{var r,n;this.session=s,(n=(r=this.delegate)===null||r===void 0?void 0:r.onCallCreated)===null||n===void 0||n.call(r)},onCallReceived:()=>{var s,r;return(r=(s=this.delegate)===null||s===void 0?void 0:s.onCallReceived)===null||r===void 0?void 0:r.call(s)},onCallHangup:()=>{var s,r;this.session=void 0,!((s=this.delegate)===null||s===void 0)&&s.onCallHangup&&((r=this.delegate)===null||r===void 0||r.onCallHangup())},onCallHold:(s,r)=>{var n,o;return(o=(n=this.delegate)===null||n===void 0?void 0:n.onCallHold)===null||o===void 0?void 0:o.call(n,r)},onCallDTMFReceived:(s,r,n)=>{var o,d;return(d=(o=this.delegate)===null||o===void 0?void 0:o.onCallDTMFReceived)===null||d===void 0?void 0:d.call(o,r,n)},onMessageReceived:s=>{var r,n;return(n=(r=this.delegate)===null||r===void 0?void 0:r.onMessageReceived)===null||n===void 0?void 0:n.call(r,s.request.body)},onRegistered:()=>{var s,r;return(r=(s=this.delegate)===null||s===void 0?void 0:s.onRegistered)===null||r===void 0?void 0:r.call(s)},onUnregistered:()=>{var s,r;return(r=(s=this.delegate)===null||s===void 0?void 0:s.onUnregistered)===null||r===void 0?void 0:r.call(s)},onServerConnect:()=>{var s,r;return(r=(s=this.delegate)===null||s===void 0?void 0:s.onServerConnect)===null||r===void 0?void 0:r.call(s)},onServerDisconnect:()=>{var s,r;return(r=(s=this.delegate)===null||s===void 0?void 0:s.onServerDisconnect)===null||r===void 0?void 0:r.call(s)}},maxSimultaneousSessions:1,media:this.options.media,reconnectionAttempts:this.options.reconnectionAttempts,reconnectionDelay:this.options.reconnectionDelay,registererOptions:this.options.registererOptions,sendDTMFUsingSessionDescriptionHandler:this.options.sendDTMFUsingSessionDescriptionHandler,userAgentOptions:this.options.userAgentOptions};this.sessionManager=new Ge(e,i),this.logger=this.sessionManager.userAgent.getLogger("sip.SimpleUser")}get id(){return this.options.userAgentOptions&&this.options.userAgentOptions.displayName||"Anonymous"}get localMediaStream(){return this.session&&this.sessionManager.getLocalMediaStream(this.session)}get remoteMediaStream(){return this.session&&this.sessionManager.getRemoteMediaStream(this.session)}get localAudioTrack(){return this.session&&this.sessionManager.getLocalAudioTrack(this.session)}get localVideoTrack(){return this.session&&this.sessionManager.getLocalVideoTrack(this.session)}get remoteAudioTrack(){return this.session&&this.sessionManager.getRemoteAudioTrack(this.session)}get remoteVideoTrack(){return this.session&&this.sessionManager.getRemoteVideoTrack(this.session)}connect(){return this.logger.log(`[${this.id}] Connecting UserAgent...`),this.sessionManager.connect()}disconnect(){return this.logger.log(`[${this.id}] Disconnecting UserAgent...`),this.sessionManager.disconnect()}isConnected(){return this.sessionManager.isConnected()}register(e){return this.logger.log(`[${this.id}] Registering UserAgent...`),this.sessionManager.register(e)}unregister(e){return this.logger.log(`[${this.id}] Unregistering UserAgent...`),this.sessionManager.unregister(e)}call(e,t,i){return this.logger.log(`[${this.id}] Beginning Session...`),this.session?Promise.reject(new Error("Session already exists.")):this.sessionManager.call(e,t,i).then(()=>{})}hangup(){return this.logger.log(`[${this.id}] Hangup...`),this.session?this.sessionManager.hangup(this.session).then(()=>{this.session=void 0}):Promise.reject(new Error("Session does not exist."))}answer(e){return this.logger.log(`[${this.id}] Accepting Invitation...`),this.session?this.sessionManager.answer(this.session,e):Promise.reject(new Error("Session does not exist."))}decline(){return this.logger.log(`[${this.id}] rejecting Invitation...`),this.session?this.sessionManager.decline(this.session):Promise.reject(new Error("Session does not exist."))}hold(){return this.logger.log(`[${this.id}] holding session...`),this.session?this.sessionManager.hold(this.session):Promise.reject(new Error("Session does not exist."))}unhold(){return this.logger.log(`[${this.id}] unholding session...`),this.session?this.sessionManager.unhold(this.session):Promise.reject(new Error("Session does not exist."))}isHeld(){return this.session?this.sessionManager.isHeld(this.session):!1}mute(){return this.logger.log(`[${this.id}] disabling media tracks...`),this.session&&this.sessionManager.mute(this.session)}unmute(){return this.logger.log(`[${this.id}] enabling media tracks...`),this.session&&this.sessionManager.unmute(this.session)}isMuted(){return this.session?this.sessionManager.isMuted(this.session):!1}sendDTMF(e){return this.logger.log(`[${this.id}] sending DTMF...`),this.session?this.sessionManager.sendDTMF(this.session,e):Promise.reject(new Error("Session does not exist."))}message(e,t){return this.logger.log(`[${this.id}] sending message...`),this.sessionManager.message(e,t)}}const bi=15e3,yi=15e3,We=(a,e,t)=>{const i=String(a?.name||a?.code||"").trim(),s=new Error(e);return s.name=i||"MediaAccessError",s.code=t,s.cause=a,s},Ke=a=>{const e=new Error(a);return e.name="SipClientLifecycleCancelledError",e.code="sip_client_replaced",e},ze=async(a,e="call")=>{const t=String(a?.name||a?.code||"").trim(),i=String(a?.message||"").trim(),s=`${t} ${i}`.toLowerCase();let r="";try{if(typeof navigator<"u"&&navigator.permissions?.query){const n=await navigator.permissions.query({name:"microphone"});r=String(n?.state||"").trim().toLowerCase()}}catch{r=""}return r==="denied"||t==="NotAllowedError"||t==="SecurityError"||s.includes("notallowederror")||s.includes("permission denied")||s.includes("permission dismissed")||s.includes("microphone permission")||s.includes("getusermedia() no permission")?We(a,`浏览器未授予麦克风权限,无法${e==="answer"?"接听来电":"发起通话"}。请点击地址栏的麦克风权限并选择“允许”,然后刷新页面重试。`,"media_permission_denied"):t==="NotFoundError"||t==="DevicesNotFoundError"||s.includes("notfounderror")||s.includes("requested device not found")||s.includes("no audio input device")?We(a,"未检测到可用的麦克风设备,无法建立语音通话。请连接耳麦或启用系统麦克风后重试。","media_device_not_found"):t==="NotReadableError"||t==="TrackStartError"||s.includes("notreadableerror")||s.includes("could not start audio source")?We(a,"麦克风当前被系统或其他应用占用,无法建立语音通话。请关闭占用麦克风的程序后重试。","media_device_unavailable"):a},vi=async(a="call")=>{if(typeof navigator>"u"||!navigator.mediaDevices?.getUserMedia)return null;let e=null;try{return e=await navigator.mediaDevices.getUserMedia({audio:!0,video:!1}),e}catch(t){throw await ze(t,a)}};class Si{constructor(e,t={}){this.account={...e},this.remoteAudioElementId=t.remoteAudioElementId||"sipRemoteAudio",this.remoteAudioElement=t.remoteAudioElement||null,this.onStateChange=t.onStateChange,this.onError=t.onError,this.onAudioLevel=t.onAudioLevel,this.onAudioFrame=t.onAudioFrame,this.simpleUser=null,this.connected=!1,this.registered=!1,this.active=!1,this.lastFailureMeta=null,this.audioContext=null,this.audioMonitors={local:null,remote:null},this.audioTrackMeta={local:null,remote:null},this.ringbackAudio=null,this.ringbackPlaying=!1,this.incomingAudio=null,this.incomingPlaying=!1,this.hangupInitiatedByLocal=!1,this.ringbackToneUrl=this._resolveToneUrl(t.ringbackTone||"ringback1.wav"),this.incomingToneUrl=this._resolveToneUrl(t.incomingTone||"ring1.wav"),this.pendingPlaybackTasks=new Map,this.audioUnlockHandler=null,this.lastSessionMeta=null,this.ensureReadyPromise=null,this.connectionWaiters=new Set,this.registrationWaiters=new Set,this.connectionConfirmTimeoutMs=Number.isFinite(Number(t.connectionConfirmTimeoutMs))?Number(t.connectionConfirmTimeoutMs):bi,this.registrationConfirmTimeoutMs=Number.isFinite(Number(t.registrationConfirmTimeoutMs))?Number(t.registrationConfirmTimeoutMs):yi,this.peerConnectionDebug={attached:!1,events:[],iceCandidates:[],iceCandidateErrors:[]}}getAudioTrackMeta(e){return e&&this.audioTrackMeta?.[e]?{...this.audioTrackMeta[e]}:null}matchesAccount(e){return this.account?this.account.sip_username===e.sip_username&&this.account.sip_domain===e.sip_domain&&(this.account.port||"443")===(e.port||"443")&&(this.account.webrtc_url||"")===(e.webrtc_url||"")&&JSON.stringify(this.account.ice_servers||[])===JSON.stringify(e.ice_servers||[]):!1}_getRemoteAudioElement(){if(this.remoteAudioElement instanceof HTMLAudioElement)return this.remoteAudioElement.autoplay=!0,this.remoteAudioElement.playsInline=!0,this.remoteAudioElement.muted=!1,this.remoteAudioElement.volume=1,this.remoteAudioElement;const e=document.getElementById(this.remoteAudioElementId);if(!(e instanceof HTMLAudioElement))throw new Error("找不到用于播放远端音频的 audio 元素");return e.autoplay=!0,e.playsInline=!0,e.muted=!1,e.volume=1,e}_getPeerConnection(){const t=this.simpleUser?.session?.sessionDescriptionHandler;return t?.peerConnection||t?._peerConnection||null}_summarizeSessionDescription(e){if(!e?.sdp)return null;const t=String(e.sdp).split(/\r?\n/).map(s=>s.trim()).filter(Boolean),i=["o=","c=","m=","a=ice-","a=candidate","a=setup:","a=fingerprint:","a=rtcp-mux","a=mid:"];return{type:e.type||"",lineCount:t.length,importantLines:t.filter(s=>i.some(r=>s.startsWith(r))),candidateLines:t.filter(s=>s.startsWith("a=candidate")),iceLines:t.filter(s=>s.startsWith("a=ice-"))}}async getMediaDiagnostics(){const e=this._getPeerConnection();this._ensurePeerConnectionDebug(e);const t=document.getElementById(this.remoteAudioElementId),i={hasPeerConnection:!!e,signalingState:e?.signalingState||"",connectionState:e?.connectionState||"",iceConnectionState:e?.iceConnectionState||"",iceGatheringState:e?.iceGatheringState||"",peerConnectionEvents:this.peerConnectionDebug.events.slice(-20),iceCandidateErrors:this.peerConnectionDebug.iceCandidateErrors.slice(-20),localDescription:this._summarizeSessionDescription(e?.localDescription),remoteDescription:this._summarizeSessionDescription(e?.remoteDescription),remoteAudio:t instanceof HTMLAudioElement?{paused:t.paused,muted:t.muted,volume:t.volume,readyState:t.readyState,currentTime:t.currentTime,srcObjectTracks:t.srcObject?.getTracks?.().map(n=>({kind:n.kind,enabled:n.enabled,muted:n.muted,readyState:n.readyState,id:n.id}))||[]}:null};if(!e||typeof e.getStats!="function")return i;const s=await e.getStats(),r={inboundAudio:null,outboundAudio:null,selectedCandidatePair:null,localCandidate:null,remoteCandidate:null,localCandidates:[],remoteCandidates:[],candidatePairs:[]};for(const n of s.values()){if(n.type==="inbound-rtp"&&n.kind==="audio"&&!n.isRemote&&(r.inboundAudio={packetsReceived:n.packetsReceived||0,bytesReceived:n.bytesReceived||0,packetsLost:n.packetsLost||0,jitter:n.jitter||0,codecId:n.codecId||"",transportId:n.transportId||""}),n.type==="outbound-rtp"&&n.kind==="audio"&&!n.isRemote&&(r.outboundAudio={packetsSent:n.packetsSent||0,bytesSent:n.bytesSent||0,retransmittedPacketsSent:n.retransmittedPacketsSent||0,codecId:n.codecId||"",transportId:n.transportId||""}),n.type==="transport"&&n.selectedCandidatePairId&&!r.selectedCandidatePair){const o=s.get(n.selectedCandidatePairId);o&&(r.selectedCandidatePair={state:o.state||"",localCandidateId:o.localCandidateId||"",remoteCandidateId:o.remoteCandidateId||"",bytesSent:o.bytesSent||0,bytesReceived:o.bytesReceived||0,currentRoundTripTime:o.currentRoundTripTime||0},r.localCandidate=s.get(o.localCandidateId)||null,r.remoteCandidate=s.get(o.remoteCandidateId)||null)}n.type==="local-candidate"&&r.localCandidates.push({id:n.id||"",candidateType:n.candidateType||"",protocol:n.protocol||"",address:n.address||n.ip||"",port:n.port||0,relayProtocol:n.relayProtocol||"",url:n.url||"",networkType:n.networkType||""}),n.type==="remote-candidate"&&r.remoteCandidates.push({id:n.id||"",candidateType:n.candidateType||"",protocol:n.protocol||"",address:n.address||n.ip||"",port:n.port||0,relayProtocol:n.relayProtocol||"",url:n.url||""}),n.type==="candidate-pair"&&r.candidatePairs.push({id:n.id||"",state:n.state||"",nominated:!!n.nominated,writable:!!n.writable,readable:!!n.readable,requestsSent:n.requestsSent||0,requestsReceived:n.requestsReceived||0,responsesSent:n.responsesSent||0,responsesReceived:n.responsesReceived||0,bytesSent:n.bytesSent||0,bytesReceived:n.bytesReceived||0,currentRoundTripTime:n.currentRoundTripTime||0,localCandidateId:n.localCandidateId||"",remoteCandidateId:n.remoteCandidateId||""})}return{...i,...r}}_ensurePeerConnectionDebug(e){if(!e||this.peerConnectionDebug.attached)return;this.peerConnectionDebug.attached=!0;const t=(i,s={})=>{this.peerConnectionDebug.events.push({type:i,timestamp:new Date().toISOString(),...s}),this.peerConnectionDebug.events.length>100&&(this.peerConnectionDebug.events=this.peerConnectionDebug.events.slice(-100))};e.addEventListener("connectionstatechange",()=>{t("connectionstatechange",{connectionState:e.connectionState||""})}),e.addEventListener("iceconnectionstatechange",()=>{t("iceconnectionstatechange",{iceConnectionState:e.iceConnectionState||""})}),e.addEventListener("icegatheringstatechange",()=>{t("icegatheringstatechange",{iceGatheringState:e.iceGatheringState||""})}),e.addEventListener("signalingstatechange",()=>{t("signalingstatechange",{signalingState:e.signalingState||""})}),e.addEventListener("icecandidate",i=>{const s=i?.candidate;if(!s){t("icecandidate-complete");return}const r={candidate:s.candidate||"",address:s.address||"",port:s.port||0,protocol:s.protocol||"",type:s.type||"",foundation:s.foundation||"",relatedAddress:s.relatedAddress||"",relatedPort:s.relatedPort||0,sdpMid:s.sdpMid||"",sdpMLineIndex:s.sdpMLineIndex??null};this.peerConnectionDebug.iceCandidates.push(r),this.peerConnectionDebug.iceCandidates.length>100&&(this.peerConnectionDebug.iceCandidates=this.peerConnectionDebug.iceCandidates.slice(-100)),t("icecandidate",r)}),e.addEventListener("icecandidateerror",i=>{const s={address:i?.address||"",port:i?.port||0,url:i?.url||"",errorCode:i?.errorCode||0,errorText:i?.errorText||""};this.peerConnectionDebug.iceCandidateErrors.push({timestamp:new Date().toISOString(),...s}),this.peerConnectionDebug.iceCandidateErrors.length>100&&(this.peerConnectionDebug.iceCandidateErrors=this.peerConnectionDebug.iceCandidateErrors.slice(-100)),t("icecandidateerror",s)}),e.addEventListener("track",i=>{t("track",{streams:Array.isArray(i?.streams)?i.streams.map(s=>({id:s.id,audioTracks:s.getAudioTracks().map(r=>({id:r.id,enabled:r.enabled,muted:r.muted,readyState:r.readyState}))})):[]})})}_createSimpleUser(){const{sip_username:e,sip_password:t,sip_domain:i,port:s,webrtc_url:r,ice_servers:n}=this.account,o=s||"443",d=r||(/^wss?:\/\//.test(i)?i:`wss://${i}:${o}`),h={aor:`sip:${e}@${i}`,media:{constraints:{audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0},video:!1},remote:{audio:this._getRemoteAudioElement()}},userAgentOptions:{authorizationUsername:e,authorizationPassword:t,sessionDescriptionHandlerFactoryOptions:{peerConnectionConfiguration:n?.length?{iceServers:n,iceTransportPolicy:"all"}:void 0}},registererOptions:{expires:1800}},m=new wi(d,h);return m.delegate={onServerConnect:()=>{this.connected=!0,this._resolveConnectionWaiters(),this.onStateChange&&this.onStateChange("connected",this.getConnectionSnapshot())},onServerDisconnect:S=>{this.connected=!1,this.registered=!1,this.active=!1,this._rejectConnectionWaiters(S||new Error("呼叫服务器已断开")),this._rejectRegistrationWaiters(S||new Error("呼叫服务器已断开")),this.onError&&this.onError(S||new Error("呼叫服务器已断开")),this.onStateChange&&this.onStateChange("disconnected",this.getConnectionSnapshot()),this._stopRingback(),this._stopIncomingTone()},onRegistered:()=>{this.registered=!0,this._resolveRegistrationWaiters(),this.onStateChange&&this.onStateChange("registered",this.getConnectionSnapshot())},onUnregistered:()=>{this.registered=!1,this._rejectRegistrationWaiters(new Error("SIP 注册已被取消或失效。")),this.onStateChange&&this.onStateChange("unregistered",this.getConnectionSnapshot())},onCallCreated:()=>{const S=this._isIncomingSession();this.lastSessionMeta=this._buildIncomingCallMeta(),!S&&this.onStateChange&&(this.onStateChange("dialing"),this._scheduleLocalMonitor())},onCallReceived:()=>{this.lastSessionMeta=this._buildIncomingCallMeta(),this._playIncomingTone(),this.onStateChange&&this.onStateChange("incoming",this._buildIncomingCallMeta())},onCallAnswered:()=>{this.active=!0,this.lastSessionMeta=this._buildIncomingCallMeta(),this.onStateChange&&this.onStateChange("answered",this._buildIncomingCallMeta()),this._stopRingback(),this._stopIncomingTone(),this._scheduleRemoteMonitor()},onCallHangup:()=>{const S=this.active;if(this.active=!1,this.onStateChange){const x=this.lastFailureMeta?{...this.lastFailureMeta}:{};x.hangupSource=this.hangupInitiatedByLocal?"local":S?"remote":"unknown";const _=this.lastSessionMeta||this._buildIncomingCallMeta();_&&Object.keys(_).length>0&&(x.callMeta=_),this.onStateChange("terminated",x)}this.hangupInitiatedByLocal=!1,this._stopAllAudioMonitors(),this._reportAudioSilence(),this._stopRingback(),this._stopIncomingTone(),this.lastFailureMeta=null,this.lastSessionMeta=null}},m}_encodeSipUserPart(e){if(!e)return"";let t=e;try{t=decodeURIComponent(e)}catch{t=e}return encodeURIComponent(t).replace(/%2B/g,"+")}_normalizeSipDestination(e){const t=(e||"").trim();if(!t)throw new Error("呼叫目标地址不能为空");const i=t.match(/^(sips?:)/i),s=i?i[1].toLowerCase():"sip:",r=i?t.slice(i[1].length):t,n=r.indexOf("@");if(n===-1)return`${s}${this._encodeSipUserPart(r)}`;const o=r.slice(0,n),d=r.slice(n+1),u=this._encodeSipUserPart(o);return`${s}${u}@${d}`}_isIncomingSession(){if(!this.simpleUser||!this.simpleUser.session)return!1;if(typeof fe<"u"&&this.simpleUser.session instanceof fe)return!0;const e=this.simpleUser.session;return!!(e&&e.incomingInviteRequest)}_buildIncomingCallMeta(){const e=this.simpleUser?.session;if(!e||!e.remoteIdentity)return{};const t=e.remoteIdentity,i=t?.uri;return{displayName:t?.displayName||t?.friendlyName||"",uri:typeof t?.toString=="function"?t.toString():i?.toString?.()||"",user:i?.user||"",host:i?.host||"",direction:this._isIncomingSession()?"inbound":"outbound"}}_assertSimpleUserIsCurrent(e,t="当前操作"){if(!(e&&this.simpleUser===e&&this.account))throw Ke(`SIP 客户端已重置,已取消${t}。`)}_resolveRegistrationWaiters(){if(!this.registrationWaiters.size)return;const e=Array.from(this.registrationWaiters);this.registrationWaiters.clear(),e.forEach(t=>{try{t.resolve()}catch{}})}_rejectRegistrationWaiters(e){if(!this.registrationWaiters.size)return;const t=Array.from(this.registrationWaiters);this.registrationWaiters.clear();const i=e instanceof Error?e:new Error("SIP 注册未完成即已中断。");t.forEach(s=>{try{s.reject(i)}catch{}})}_resolveConnectionWaiters(){if(!this.connectionWaiters.size)return;const e=Array.from(this.connectionWaiters);this.connectionWaiters.clear(),e.forEach(t=>{try{t.resolve()}catch{}})}_rejectConnectionWaiters(e){if(!this.connectionWaiters.size)return;const t=Array.from(this.connectionWaiters);this.connectionWaiters.clear();const i=e instanceof Error?e:new Error("SIP 连接未完成即已中断。");t.forEach(s=>{try{s.reject(i)}catch{}})}_waitForConnectionConfirmation(e=this.connectionConfirmTimeoutMs){return this.connected?Promise.resolve():new Promise((t,i)=>{const s={resolve:()=>{clearTimeout(r),t()},reject:n=>{clearTimeout(r),i(n)}},r=setTimeout(()=>{this.connectionWaiters.delete(s);const n=this.account?.internal_number||this.account?.account_key||this.account?.sip_username||"当前账号";i(new Error(`${n} 浏览器连接超时,未收到 SIP 服务器连接确认。`))},e);this.connectionWaiters.add(s)})}_waitForRegistrationConfirmation(e=this.registrationConfirmTimeoutMs){return this.registered?Promise.resolve():new Promise((t,i)=>{const s={resolve:()=>{clearTimeout(r),t()},reject:n=>{clearTimeout(r),i(n)}},r=setTimeout(()=>{this.registrationWaiters.delete(s);const n=this.account?.internal_number||this.account?.account_key||this.account?.sip_username||"当前账号";i(new Error(`${n} 浏览器注册超时,信令已连接但未收到注册确认。`))},e);this.registrationWaiters.add(s)})}_captureRegistrationDiagnostics(){return{snapshot:this.getConnectionSnapshot(),shouldBeRegistered:!!this.simpleUser?.sessionManager?.shouldBeRegistered,hasRegisterer:!!this.simpleUser?.sessionManager?.registerer}}_shouldRecoverFromConnectedWithoutRegistration(e){return!!(e?.snapshot?.connected&&!e?.snapshot?.registered&&!e?.shouldBeRegistered&&!e?.hasRegisterer)}async _ensureRegistration(e){try{this._assertSimpleUserIsCurrent(e,"注册流程"),await e.register(),this._assertSimpleUserIsCurrent(e,"注册流程"),this.registered||(await this._waitForRegistrationConfirmation(),this._assertSimpleUserIsCurrent(e,"注册确认"))}catch(t){throw this.onError&&this.onError(t),t}}async ensureReady(){if(this.ensureReadyPromise)return this.ensureReadyPromise;const e=(async()=>{let t=this.simpleUser;if(t||(t=this._createSimpleUser(),this.simpleUser=t),!this.connected){let i=null;const s=t.connect().catch(r=>(i=r,null));if(this.connected||await Promise.race([s,this._waitForConnectionConfirmation()]),this.connected||await s,i)throw i;this.connected||await this._waitForConnectionConfirmation(),this._assertSimpleUserIsCurrent(t,"连接流程"),this.connected=!0,this.onStateChange&&this.onStateChange("connected",this.getConnectionSnapshot())}if(!this.registered){let i=null;try{await this._ensureRegistration(t)}catch(r){i=r}let s=this._captureRegistrationDiagnostics();if(i&&this._shouldRecoverFromConnectedWithoutRegistration(s)){console.info("SIP 客户端首次建连后未真正进入注册流程,开始立即补注册。",{accountKey:this.account?.internal_number||this.account?.account_key||this.account?.sip_username||null,snapshot:s.snapshot}),await new Promise(r=>window.setTimeout(r,200));try{await this._ensureRegistration(t)}catch(r){i=i||r}s=this._captureRegistrationDiagnostics()}if(i&&!(s?.snapshot?.connected&&s?.snapshot?.registered))throw i}})().finally(()=>{this.ensureReadyPromise===e&&(this.ensureReadyPromise=null)});return this.ensureReadyPromise=e,e}getConnectionSnapshot(){const e=this.simpleUser,t=typeof e?.isConnected=="function"?e.isConnected():!!this.connected,i=typeof e?.isRegistered=="function"?e.isRegistered():!!this.registered;return{connected:t,registered:i,active:!!this.active,sipDomain:this.account?.sip_domain||"",transportUrl:this.account?.webrtc_url||""}}async disconnect(e={}){const{unregister:t=!0}=e||{};if(!this.simpleUser){this.connected=!1,this.registered=!1,this.onStateChange&&this.onStateChange("disconnected",this.getConnectionSnapshot());return}const i=[];t&&this.registered&&i.push(this.simpleUser.unregister().catch(s=>{this.onError&&this.onError(s)})),this.connected&&i.push(this.simpleUser.disconnect().catch(s=>{this.onError&&this.onError(s)})),await Promise.all(i),this.connected=!1,this.registered=!1,this.active=!1,this._stopAllAudioMonitors(),this._reportAudioSilence(),this._stopRingback(),this._stopIncomingTone(),this._clearAutoplayUnlockTasks(),this.onStateChange&&this.onStateChange("disconnected",this.getConnectionSnapshot())}async reconnect(){await this.disconnect(),await this.ensureReady()}async call(e,t){if(!e)throw new Error("电话号码不能为空");this.lastFailureMeta=null,this.hangupInitiatedByLocal=!1,await this.ensureReady();const i=String(e).trim();let s;/^sips?:/i.test(i)?s=i:i.includes("@")?s=`sip:${i}`:s=`sip:${i}@${this.account.sip_domain}`,s=this._normalizeSipDestination(s);const r=this._createInviteRequestDelegate(t),n=this._mergeInviteOptions(t,r);try{await this._preflightAudioAccess("call"),await this.simpleUser.call(s,void 0,n),this._scheduleLocalMonitor(),this._stopIncomingTone()}catch(o){const d=await this._normalizeMediaAccessError(o,"call");throw this.onError&&this.onError(d),this.lastFailureMeta={source:"invite-exception",code:d?.code||null,message:d?.message||"呼叫请求失败",timestamp:new Date().toISOString()},this.onStateChange&&this.onStateChange("failed",{...this.lastFailureMeta}),d}}async _preflightAudioAccess(e="call"){let t=null;try{t=await vi(e)}catch(i){const s=await ze(i,e);throw this.onError&&this.onError(s),this.lastFailureMeta={source:"media-preflight",code:s?.code||null,message:s?.message||"媒体设备检查失败",timestamp:new Date().toISOString()},this.onStateChange&&this.onStateChange("failed",{...this.lastFailureMeta}),s}finally{t?.getTracks?.().forEach(i=>{try{i.stop()}catch{}})}}_mergeInviteOptions(e,t){const i={...e||{}};return i.requestDelegate=t.requestDelegate,i}_handleInviteProgress(e){const t=e?.message;if(!t)return;const i=t.statusCode||0;if(i>=180&&i<200){const s=this._extractResponseMeta("progress",e);console.info("[CALL] 呼叫收到临时响应",s),this._isIncomingSession()||(this.onStateChange&&this.onStateChange(i===180?"ringing":"dialing",s),i===180&&this._playRingback())}}_handleInviteFailure(e,t){const i=this._extractResponseMeta(e,t);this.lastFailureMeta=i,console.warn("[CALL] 呼叫失败",i),this._stopRingback(),this._stopIncomingTone(),this._stopAllAudioMonitors(),this._reportAudioSilence(),this.onStateChange&&this.onStateChange("failed",{...i}),this.onError&&i.message&&this.onError(new Error(i.message))}_extractResponseMeta(e,t){const i=t?.message,s=i?.statusCode||null,r=(i?.reasonPhrase||"").trim(),n=this._getHeaderValue(i,"Warning"),o=this._getHeaderValue(i,"Reason"),d=this._getHeaderValue(i,"Retry-After"),u=typeof i?.body=="string"?i.body.trim():"",m=[s,r].filter(Boolean).join(" ").trim()||n||o||u||"呼叫未建立";return{source:"invite-response",stage:e,status:s,reason:r,warning:n,cause:o,retryAfter:d,body:u,message:m,timestamp:new Date().toISOString()}}_getHeaderValue(e,t){if(!e||typeof e.getHeader!="function")return"";try{const i=e.getHeader(t);return i?String(i).trim():""}catch{return""}}async _normalizeMediaAccessError(e,t="call"){return ze(e,t)}_createInviteRequestDelegate(e){const t=(s,...r)=>{if(typeof s=="function")try{s(...r)}catch(n){console.warn("SIP 邀请回调执行异常",n)}},i=e?.requestDelegate||{};return{requestDelegate:{onAccept:(...s)=>{this.lastFailureMeta=null,t(i.onAccept,...s)},onRedirect:(s,...r)=>{this._handleInviteFailure("redirect",s),t(i.onRedirect,s,...r)},onReject:(s,...r)=>{this._handleInviteFailure("reject",s),t(i.onReject,s,...r)},onProgress:(s,...r)=>{this._handleInviteProgress(s),t(i.onProgress,s,...r)},onTrying:(...s)=>{t(i.onTrying,...s)}}}}async answer(e){if(!this.simpleUser)throw new Error("呼叫客户端未初始化");try{await this._preflightAudioAccess("answer"),this._stopIncomingTone(),this._stopRingback(),await this.simpleUser.answer(e),this._scheduleLocalMonitor()}catch(t){const i=await this._normalizeMediaAccessError(t,"answer");throw this.onError&&this.onError(i),i}}async decline(){if(!this.simpleUser){this._stopAllAudioMonitors(),this._reportAudioSilence(),this._stopRingback(),this._stopIncomingTone();return}let e=null;try{await this.simpleUser.decline()}catch(t){e=t,this.onError&&this.onError(t)}finally{this._stopAllAudioMonitors(),this._reportAudioSilence(),this._stopRingback(),this._stopIncomingTone()}if(e)throw e}async hangup(){if(!this.simpleUser){this._stopAllAudioMonitors(),this._reportAudioSilence(),this._stopRingback(),this._stopIncomingTone();return}let e=null;try{this.hangupInitiatedByLocal=!0,await this.simpleUser.hangup()}catch(t){e=t,this.onError&&this.onError(t)}finally{this._stopAllAudioMonitors(),this._reportAudioSilence(),this._stopRingback(),this._stopIncomingTone()}if(e)throw e}mute(){if(this.simpleUser)try{this.simpleUser.mute()}catch(e){throw this.onError&&this.onError(e),e}}unmute(){if(this.simpleUser)try{this.simpleUser.unmute()}catch(e){throw this.onError&&this.onError(e),e}}async hold(){if(this.simpleUser)try{await this.simpleUser.hold()}catch(e){throw this.onError&&this.onError(e),e}}async unhold(){if(this.simpleUser)try{await this.simpleUser.unhold()}catch(e){throw this.onError&&this.onError(e),e}}async destroy(){this._rejectConnectionWaiters(Ke("SIP 客户端已销毁,已取消连接等待。")),this._rejectRegistrationWaiters(Ke("SIP 客户端已销毁,已取消注册等待。")),this.ensureReadyPromise=null;const e=this.simpleUser;if(e)try{this.registered&&await e.unregister(),this.connected&&await e.disconnect()}catch(t){this.onError&&this.onError(t)}this._stopAllAudioMonitors(),this._closeAudioContext(),this._stopRingback(),this._stopIncomingTone(),this._clearAutoplayUnlockTasks(),this.simpleUser=null,this.connected=!1,this.registered=!1,this.active=!1,this.account=null,this.audioTrackMeta={local:null,remote:null},this.peerConnectionDebug={attached:!1,events:[],iceCandidates:[],iceCandidateErrors:[]}}_scheduleLocalMonitor(e=0){if(!this.onAudioLevel)return;const t=this.simpleUser?.localMediaStream;if(t instanceof MediaStream&&t.getAudioTracks().length>0){this._startAudioLevelMonitor("local",t);return}e>10||setTimeout(()=>this._scheduleLocalMonitor(e+1),200*(e+1))}_scheduleRemoteMonitor(e=0){if(!this.onAudioLevel||!this.simpleUser)return;const t=this.simpleUser.remoteMediaStream||this._getRemoteAudioElement()?.srcObject;if(t instanceof MediaStream&&t.getAudioTracks&&t.getAudioTracks().length>0){this._startAudioLevelMonitor("remote",t);return}e>10||setTimeout(()=>this._scheduleRemoteMonitor(e+1),300*(e+1))}_startAudioLevelMonitor(e,t){if(!(!this.onAudioLevel&&!this.onAudioFrame)&&t instanceof MediaStream&&!(t.getAudioTracks&&t.getAudioTracks().length===0)&&this._ensureAudioContext()){try{if(t.getAudioTracks&&typeof t.getAudioTracks=="function"){const[i]=t.getAudioTracks();if(i){const s={track_id:i.id||null,label:i.label||null};try{s.settings=i.getSettings?i.getSettings():void 0}catch{s.settings=void 0}try{s.constraints=i.getConstraints?i.getConstraints():void 0}catch{s.constraints=void 0}this.audioTrackMeta=this.audioTrackMeta||{},this.audioTrackMeta[e]=s}}}catch{}this._stopAudioLevelMonitor(e);try{const i=this.audioContext.createMediaStreamSource(t),s=this.audioContext.createAnalyser();s.fftSize=2048;const r=new Uint8Array(s.fftSize);i.connect(s);const n=typeof this.onAudioFrame=="function",o=()=>{s.getByteTimeDomainData(r);let u=0;const h=n?new Float32Array(r.length):null;for(let _=0;_<r.length;_+=1){const C=(r[_]-128)/128;u+=C*C,h&&(h[_]=C)}const m=Math.sqrt(u/r.length),S=Math.min(1,m*2);if(this.onAudioLevel&&this.onAudioLevel(e,S),h&&this.audioContext&&this.onAudioFrame)try{this.onAudioFrame(e,{samples:h,sampleRate:this.audioContext.sampleRate||48e3,timestamp:Date.now()})}catch{}const x=this.audioMonitors[e];x&&(x.rafId=window.requestAnimationFrame(o))},d={source:i,analyser:s,dataArray:r,rafId:window.requestAnimationFrame(o)};this.audioMonitors[e]=d}catch(i){this.onError&&this.onError(i)}}}_stopAudioLevelMonitor(e){const t=this.audioMonitors[e];if(t){t.rafId&&window.cancelAnimationFrame(t.rafId);try{t.source&&t.source.disconnect()}catch{}delete this.audioMonitors[e]}}_stopAllAudioMonitors(){this._stopAudioLevelMonitor("local"),this._stopAudioLevelMonitor("remote"),!this.audioMonitors.local&&!this.audioMonitors.remote&&this._closeAudioContext()}_resolveToneUrl(e){return e?e.startsWith("http://")||e.startsWith("https://")||e.startsWith("/")?e:`/assets/${e}`:null}_normalizeAudioUrl(e){if(!e)return"";if(typeof window>"u")return e;try{const t=window.location?.origin||window.location?.href;return t?new URL(e,t).href:e}catch{return e}}_getAudioSourceMeta(e){return e?e._sipToneSrc?e._sipToneSrc:e.dataset&&e.dataset.sipToneSrc?e.dataset.sipToneSrc:this._normalizeAudioUrl(e.src||""):""}_markAudioSourceMeta(e,t){e&&(e.dataset&&(e.dataset.sipToneSrc=t),e._sipToneSrc=t)}_loadAudio(e,t){if(!e||typeof window>"u")return null;const i=this._normalizeAudioUrl(e);if(t){if(this._getAudioSourceMeta(t)===i)return t;try{t.pause(),t.currentTime=0}catch(r){console.warn("停止旧音频失败:",r)}}try{const s=new Audio(i);return s.loop=!0,s.preload="auto",s.volume=.6,s.playsInline=!0,s.autoplay=!0,this._markAudioSourceMeta(s,i),s}catch(s){return console.warn("创建音频失败:",s),null}}_shouldUnlock(e){if(!e)return!1;const t=e.name||e.code||"";return t==="NotAllowedError"||t==="SecurityError"}_attemptPlayAudio(e,{onSuccess:t,onError:i,unlockKey:s}){if(!e)return!1;this._ensureAudioContext();const r=()=>{typeof t=="function"&&t(),s&&this._removePendingPlaybackTask(s)},n=o=>{if(this._shouldUnlock(o)&&s){this._requestAutoplayUnlock(s,()=>{this._attemptPlayAudio(e,{onSuccess:t,onError:i,unlockKey:s})});return}typeof i=="function"&&i(o)};try{const o=e.play();o&&typeof o.then=="function"?o.then(()=>r()).catch(d=>n(d)):r()}catch(o){n(o)}return!0}_requestAutoplayUnlock(e,t){!e||typeof t!="function"||(this.pendingPlaybackTasks instanceof Map||(this.pendingPlaybackTasks=new Map),this.pendingPlaybackTasks.has(e)||this.pendingPlaybackTasks.set(e,t),!this.audioUnlockHandler&&typeof document<"u"&&(this.audioUnlockHandler=()=>{this._flushAutoplayTasks()},document.addEventListener("click",this.audioUnlockHandler,!0),document.addEventListener("touchstart",this.audioUnlockHandler,!0),document.addEventListener("keydown",this.audioUnlockHandler,!0)))}_flushAutoplayTasks(){if(!(this.pendingPlaybackTasks instanceof Map)||this.pendingPlaybackTasks.size===0){this._removeAudioUnlockHandler();return}const e=Array.from(this.pendingPlaybackTasks.entries());this.pendingPlaybackTasks.clear(),e.forEach(([t,i])=>{try{i()}catch(s){console.warn("触发音频播放失败:",s),this.pendingPlaybackTasks instanceof Map&&this.pendingPlaybackTasks.set(t,i)}}),(!(this.pendingPlaybackTasks instanceof Map)||this.pendingPlaybackTasks.size===0)&&this._removeAudioUnlockHandler()}_removeAudioUnlockHandler(){!this.audioUnlockHandler||typeof document>"u"||(document.removeEventListener("click",this.audioUnlockHandler,!0),document.removeEventListener("touchstart",this.audioUnlockHandler,!0),document.removeEventListener("keydown",this.audioUnlockHandler,!0),this.audioUnlockHandler=null)}_removePendingPlaybackTask(e){this.pendingPlaybackTasks instanceof Map&&(this.pendingPlaybackTasks.delete(e),this.pendingPlaybackTasks.size===0&&this._removeAudioUnlockHandler())}_clearAutoplayUnlockTasks(){this.pendingPlaybackTasks instanceof Map&&this.pendingPlaybackTasks.clear(),this._removeAudioUnlockHandler()}_playRingback(){this.ringbackPlaying||(this.ringbackAudio=this._loadAudio(this.ringbackToneUrl,this.ringbackAudio),this.ringbackAudio&&this._attemptPlayAudio(this.ringbackAudio,{unlockKey:"ringback",onSuccess:()=>{this.ringbackPlaying=!0},onError:e=>{this.ringbackPlaying=!1,console.warn("播放回铃音异常:",e)}}))}_stopRingback(){if(this.ringbackAudio){try{this.ringbackAudio.pause(),this.ringbackAudio.currentTime=0}catch(e){console.warn("停止回铃音异常:",e)}this.ringbackPlaying=!1,this._removePendingPlaybackTask("ringback")}}_playIncomingTone(){this.incomingPlaying||(this.incomingAudio=this._loadAudio(this.incomingToneUrl,this.incomingAudio),this.incomingAudio&&this._attemptPlayAudio(this.incomingAudio,{unlockKey:"incoming",onSuccess:()=>{this.incomingPlaying=!0},onError:e=>{this.incomingPlaying=!1,console.warn("播放振铃音异常:",e)}}))}_stopIncomingTone(){if(this.incomingAudio){try{this.incomingAudio.pause(),this.incomingAudio.currentTime=0}catch(e){console.warn("停止振铃音异常:",e)}this.incomingPlaying=!1,this._removePendingPlaybackTask("incoming")}}updateToneOptions({ringbackTone:e,incomingTone:t}){if(e){const i=this._resolveToneUrl(e);i&&i!==this.ringbackToneUrl&&(this._stopRingback(),this.ringbackToneUrl=i,this.ringbackAudio=null)}if(t){const i=this._resolveToneUrl(t);i&&i!==this.incomingToneUrl&&(this._stopIncomingTone(),this.incomingToneUrl=i,this.incomingAudio=null)}}silenceIncomingTone(){this._stopIncomingTone()}_reportAudioSilence(){this.onAudioLevel&&(this.onAudioLevel("local",0),this.onAudioLevel("remote",0))}_ensureAudioContext(){if(typeof window>"u"||!window.AudioContext&&!window.webkitAudioContext)return!1;if(!this.audioContext){const e=window.AudioContext||window.webkitAudioContext;this.audioContext=new e}return this.audioContext.state==="suspended"&&this.audioContext.resume().catch(()=>{}),!0}_closeAudioContext(){if(this.audioContext)try{this.audioContext.close()}catch{}this.audioContext=null}}const Ti=/^[a-z][a-z0-9+.-]*:\/\//i;function Ci(a,e=""){const t=String(a||e||"").trim();if(!t)throw new Error("缺少统一服务基址");return t}function bt(a,e="https://"){return Ti.test(a)?a:`${e}${a.replace(/^\/+/,"")}`}function Ye(a="/"){return a.endsWith("/")?a:`${a}/`}function yt(a="/",e=""){const t=Ye(a||"/"),i=String(e||"").replace(/^\/+/,"");return i?`${t}${i}`:t}function ye(a=""){return String(a||"").replace(/^\/+/,"")}function vt(a=""){const e=String(a||""),t=e.indexOf("?");return t<0?{pathname:ye(e),search:""}:{pathname:ye(e.slice(0,t)),search:e.slice(t)}}function Ei(a="/",e="/"){const t=String(a||"/"),i=Ye(e||"/");return i!=="/"&&t.startsWith(i)?ye(t.slice(i.length)):ye(t)}function _e(a,e=""){const t=bt(Ci(a,e)),i=new URL(t);return i.search="",i.hash="",i.pathname=Ye(i.pathname||"/"),i}function xi(a,e=""){return _e(a,e).pathname!=="/"}function X(a,e,t=""){const i=_e(a,t),s=vt(e);return i.pathname=yt(i.pathname,s.pathname),i.search=s.search,i.href}function Je(a,e="ws",t=""){const i=_e(a,t);i.protocol==="https:"?i.protocol="wss:":i.protocol==="http:"?i.protocol="ws:":i.protocol!=="ws:"&&i.protocol!=="wss:"&&(i.protocol="wss:");const s=vt(e);return i.pathname=yt(i.pathname,s.pathname),i.search=s.search,i.href}function St(a,e="",t=""){if(!String(a||"").trim())return ye(e);const i=new URL(bt(String(a).trim())),s=String(t||"").trim()?_e(t).pathname:"/",r=Ei(i.pathname||"/",s),n=String(i.search||"");return`${r}${n}`||ye(e)}function Tt({apiBaseUrl:a,transportBaseUrl:e="",transportUrl:t="",fallbackPath:i="ws"}){const s=String(e||"").trim();return s?Je(s,St(t,i,s)):xi(a)?Je(a,St(t,i,a)):String(t||"").trim()?String(t).trim():Je(a,i)}const _i=`
|
|
66
66
|
:host { all: initial; }
|
|
67
|
-
.widget {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
67
|
+
.widget {
|
|
68
|
+
position: relative;
|
|
69
|
+
display: inline-flex;
|
|
70
|
+
flex-direction: column;
|
|
71
|
+
gap: 14px;
|
|
72
|
+
font-family: "Noto Sans SC", "PingFang SC", sans-serif;
|
|
73
|
+
color: #16302b;
|
|
74
|
+
}
|
|
75
|
+
.trigger {
|
|
76
|
+
position: relative;
|
|
77
|
+
display: inline-flex;
|
|
78
|
+
align-items: center;
|
|
79
|
+
justify-content: center;
|
|
80
|
+
width: 60px;
|
|
81
|
+
height: 60px;
|
|
82
|
+
border: 0;
|
|
83
|
+
border-radius: 999px;
|
|
84
|
+
background: linear-gradient(135deg, #0f766e, #0b5b63);
|
|
85
|
+
color: #f8faf8;
|
|
86
|
+
box-shadow: 0 18px 36px rgba(11, 91, 99, 0.28);
|
|
87
|
+
cursor: pointer;
|
|
88
|
+
}
|
|
89
|
+
.trigger[disabled] {
|
|
90
|
+
cursor: not-allowed;
|
|
91
|
+
opacity: 0.72;
|
|
92
|
+
}
|
|
93
|
+
.trigger svg {
|
|
94
|
+
width: 24px;
|
|
95
|
+
height: 24px;
|
|
96
|
+
}
|
|
97
|
+
.trigger-badge {
|
|
98
|
+
position: absolute;
|
|
99
|
+
top: 6px;
|
|
100
|
+
right: 4px;
|
|
101
|
+
min-width: 10px;
|
|
102
|
+
height: 10px;
|
|
103
|
+
padding: 0 4px;
|
|
104
|
+
border-radius: 999px;
|
|
105
|
+
background: #e11d48;
|
|
106
|
+
color: #ffffff;
|
|
107
|
+
font-size: 11px;
|
|
108
|
+
font-weight: 700;
|
|
109
|
+
line-height: 18px;
|
|
110
|
+
text-align: center;
|
|
111
|
+
box-shadow: 0 0 0 3px rgba(248, 250, 248, 0.92);
|
|
112
|
+
}
|
|
113
|
+
.trigger-badge--dot {
|
|
114
|
+
padding: 0;
|
|
115
|
+
min-width: 10px;
|
|
116
|
+
height: 10px;
|
|
117
|
+
line-height: 10px;
|
|
118
|
+
}
|
|
119
|
+
.trigger-badge[hidden] {
|
|
120
|
+
display: none;
|
|
121
|
+
}
|
|
122
|
+
.sr-only {
|
|
123
|
+
position: absolute;
|
|
124
|
+
width: 1px;
|
|
125
|
+
height: 1px;
|
|
126
|
+
padding: 0;
|
|
127
|
+
margin: -1px;
|
|
128
|
+
overflow: hidden;
|
|
129
|
+
clip: rect(0, 0, 0, 0);
|
|
130
|
+
white-space: nowrap;
|
|
131
|
+
border: 0;
|
|
132
|
+
}
|
|
133
|
+
.panel-shell {
|
|
134
|
+
position: fixed;
|
|
135
|
+
inset: 0;
|
|
136
|
+
display: flex;
|
|
137
|
+
align-items: flex-end;
|
|
138
|
+
justify-content: flex-end;
|
|
139
|
+
padding: 24px;
|
|
140
|
+
pointer-events: none;
|
|
141
|
+
z-index: 2147483000;
|
|
142
|
+
}
|
|
143
|
+
.panel-shell--visible {
|
|
144
|
+
pointer-events: auto;
|
|
145
|
+
}
|
|
146
|
+
.panel-backdrop {
|
|
147
|
+
position: absolute;
|
|
148
|
+
inset: 0;
|
|
149
|
+
background: rgba(11, 23, 21, 0.22);
|
|
150
|
+
opacity: 0;
|
|
151
|
+
transition: opacity 140ms ease;
|
|
152
|
+
}
|
|
153
|
+
.panel-shell--visible .panel-backdrop {
|
|
154
|
+
opacity: 1;
|
|
155
|
+
}
|
|
156
|
+
.panel {
|
|
157
|
+
position: relative;
|
|
158
|
+
width: min(360px, calc(100vw - 32px));
|
|
159
|
+
border-radius: 28px;
|
|
160
|
+
overflow: hidden;
|
|
161
|
+
background: linear-gradient(180deg, #fffdf8 0%, #f4efe6 100%);
|
|
162
|
+
border: 1px solid rgba(17, 100, 102, 0.12);
|
|
163
|
+
box-shadow: 0 28px 68px rgba(17, 30, 28, 0.24);
|
|
164
|
+
transform: translateY(18px) scale(0.98);
|
|
165
|
+
opacity: 0;
|
|
166
|
+
transition: transform 160ms ease, opacity 160ms ease;
|
|
167
|
+
}
|
|
168
|
+
.panel-shell--visible .panel {
|
|
169
|
+
transform: translateY(0) scale(1);
|
|
170
|
+
opacity: 1;
|
|
171
|
+
}
|
|
172
|
+
.panel-hero {
|
|
173
|
+
padding: 20px 20px 18px;
|
|
174
|
+
background:
|
|
175
|
+
radial-gradient(circle at top right, rgba(44, 120, 115, 0.2), transparent 42%),
|
|
176
|
+
linear-gradient(135deg, #fef9ef, #edf7f2);
|
|
177
|
+
}
|
|
178
|
+
.panel-eyebrow {
|
|
179
|
+
margin: 0 0 8px;
|
|
180
|
+
font-size: 11px;
|
|
181
|
+
font-weight: 700;
|
|
182
|
+
letter-spacing: 0.12em;
|
|
183
|
+
text-transform: uppercase;
|
|
184
|
+
color: #2c7873;
|
|
185
|
+
}
|
|
186
|
+
.panel-title {
|
|
187
|
+
margin: 0;
|
|
188
|
+
font-size: 22px;
|
|
189
|
+
line-height: 1.25;
|
|
190
|
+
}
|
|
191
|
+
.status {
|
|
192
|
+
margin: 12px 0 0;
|
|
193
|
+
font-size: 16px;
|
|
194
|
+
font-weight: 700;
|
|
195
|
+
color: #133a34;
|
|
196
|
+
}
|
|
197
|
+
.status--failed {
|
|
198
|
+
color: #9f1239;
|
|
199
|
+
}
|
|
200
|
+
.panel-detail {
|
|
201
|
+
margin: 10px 0 0;
|
|
202
|
+
font-size: 13px;
|
|
203
|
+
line-height: 1.6;
|
|
204
|
+
color: #355b54;
|
|
205
|
+
}
|
|
206
|
+
.actions {
|
|
207
|
+
display: grid;
|
|
208
|
+
gap: 10px;
|
|
209
|
+
padding: 0 20px 20px;
|
|
210
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
211
|
+
}
|
|
212
|
+
.actions--single {
|
|
213
|
+
grid-template-columns: 1fr;
|
|
214
|
+
}
|
|
215
|
+
.btn {
|
|
216
|
+
appearance: none;
|
|
217
|
+
border: 0;
|
|
218
|
+
border-radius: 18px;
|
|
219
|
+
padding: 13px 14px;
|
|
220
|
+
font-size: 15px;
|
|
221
|
+
font-weight: 700;
|
|
222
|
+
cursor: pointer;
|
|
223
|
+
}
|
|
224
|
+
.btn[hidden] {
|
|
225
|
+
display: none;
|
|
226
|
+
}
|
|
227
|
+
.btn-primary {
|
|
228
|
+
background: #116466;
|
|
229
|
+
color: #f7f3e9;
|
|
230
|
+
}
|
|
231
|
+
.btn-secondary {
|
|
232
|
+
background: #dfeee7;
|
|
233
|
+
color: #16302b;
|
|
234
|
+
}
|
|
235
|
+
.btn-danger {
|
|
236
|
+
background: #16302b;
|
|
237
|
+
color: #f8faf8;
|
|
238
|
+
}
|
|
239
|
+
.btn[disabled] {
|
|
240
|
+
opacity: 0.55;
|
|
241
|
+
cursor: not-allowed;
|
|
242
|
+
}
|
|
243
|
+
.debug-panel {
|
|
244
|
+
width: min(360px, calc(100vw - 32px));
|
|
245
|
+
border-radius: 22px;
|
|
246
|
+
overflow: hidden;
|
|
247
|
+
background: rgba(250, 252, 251, 0.96);
|
|
248
|
+
border: 1px solid rgba(17, 100, 102, 0.14);
|
|
249
|
+
box-shadow: 0 18px 42px rgba(17, 30, 28, 0.14);
|
|
250
|
+
}
|
|
251
|
+
.debug-panel[hidden] {
|
|
252
|
+
display: none;
|
|
253
|
+
}
|
|
254
|
+
.availability { display: inline-flex; align-items: center; gap: 6px; margin: 16px 16px 0; padding: 7px 10px; border-radius: 999px; font-size: 12px; font-weight: 700; }
|
|
73
255
|
.availability--ready { color: #0f5132; background: rgba(220, 252, 231, 0.92); }
|
|
74
256
|
.availability--preparing { color: #0b4f71; background: rgba(225, 239, 255, 0.96); }
|
|
75
257
|
.availability--working { color: #0b4f71; background: rgba(220, 240, 255, 0.96); }
|
|
76
258
|
.availability--recovering { color: #8a5a00; background: rgba(255, 244, 200, 0.96); }
|
|
77
259
|
.availability--offline { color: #8b1e3f; background: rgba(255, 226, 231, 0.96); }
|
|
78
260
|
.availability--conflicted { color: #6f1d1b; background: rgba(255, 233, 228, 0.96); }
|
|
79
|
-
.
|
|
80
|
-
.
|
|
81
|
-
.
|
|
82
|
-
.status--conflicted { border: 1px solid rgba(180, 55, 41, 0.24); background: rgba(255, 241, 238, 0.97); color: #7f231e; }
|
|
83
|
-
.hint { margin-top: 10px; font-size: 12px; line-height: 1.5; color: #355b54; }
|
|
84
|
-
.meta { padding: 14px 18px; font-size: 13px; line-height: 1.6; border-top: 1px solid rgba(28, 78, 67, 0.08); }
|
|
85
|
-
.actions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; padding: 0 18px 18px; }
|
|
86
|
-
.btn { appearance: none; border: 0; border-radius: 16px; padding: 12px 14px; font-size: 14px; cursor: pointer; }
|
|
87
|
-
.btn-primary { background: #116466; color: #f7f3e9; }
|
|
88
|
-
.btn-secondary { background: #dfeee7; color: #16302b; }
|
|
89
|
-
.btn[disabled] { opacity: 0.55; cursor: not-allowed; }
|
|
90
|
-
.logs { max-height: 160px; overflow: auto; padding: 0 18px 18px; display: grid; gap: 8px; }
|
|
261
|
+
.meta { padding: 14px 16px 0; font-size: 13px; line-height: 1.6; }
|
|
262
|
+
.hint { padding: 10px 16px 0; font-size: 12px; line-height: 1.6; color: #355b54; }
|
|
263
|
+
.logs { max-height: 180px; overflow: auto; padding: 14px 16px 16px; display: grid; gap: 8px; }
|
|
91
264
|
.log { padding: 10px 12px; border-radius: 14px; background: rgba(255,255,255,0.74); font-size: 12px; line-height: 1.5; white-space: pre-wrap; }
|
|
92
265
|
.audio { display: none; }
|
|
93
266
|
@media (max-width: 480px) {
|
|
94
|
-
.panel {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
.
|
|
100
|
-
.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
267
|
+
.panel-shell {
|
|
268
|
+
align-items: flex-end;
|
|
269
|
+
justify-content: center;
|
|
270
|
+
padding: 12px;
|
|
271
|
+
}
|
|
272
|
+
.panel,
|
|
273
|
+
.debug-panel {
|
|
274
|
+
width: min(100vw - 24px, 100%);
|
|
275
|
+
}
|
|
276
|
+
.panel-title { font-size: 20px; }
|
|
277
|
+
.actions {
|
|
278
|
+
grid-template-columns: 1fr;
|
|
279
|
+
padding: 0 16px 16px;
|
|
280
|
+
}
|
|
281
|
+
.btn { min-height: 46px; }
|
|
282
|
+
.meta { padding: 12px 16px 0; font-size: 12px; }
|
|
283
|
+
.logs { max-height: 150px; padding: 12px 16px 16px; }
|
|
284
|
+
}
|
|
285
|
+
`,ie={idle:"网页电话已加载,正在准备待机能力。",requesting:"正在向服务端申请网页通话会话。",standbyRequesting:"正在向服务端申请 widget 待机会话。",registering:"临时账号已拿到,正在连接并执行 REGISTER。",standby:"REGISTER 已完成,widget 正在等待来电。",incoming:"收到新的来电,请选择接听或拒接。",calling:"已发起呼叫,正在等待对端振铃或接听。",connected:"通话已接通,媒体链路正在运行。",ended:"通话已结束,网页电话正在返回待机。",rejected:"本次来电已拒接,widget 仍保持待机。",missed:"本次来电未接听,widget 仍保持待机。",failed:"本次呼叫失败,请先看下方日志。"},Ze={idle:"准备通话",ringing:"来电中",dialing:"拨打中",connected:"通话中",ended:"已结束",failed:"当前暂时无法接通"},Ri="手机网页首次接入时,请允许麦克风权限;若切到后台后再回来,先确认页面仍保持前台活跃。",Ii=1500,Ai=5e3,$i=15e3,Ct=2,Re=3e4,Di=1200,Pi=3e4,ki=4e3,Hi="embedded-call-widget:first-hint-dismissed:",de={ready:"线路可用",preparing:"正在准备",working:"通话处理中",recovering:"正在恢复",offline:"当前离线",conflicted:"协议冲突"},Ie=Object.freeze({standby:"widget_standby",outbound:"outbound"}),Et=Object.freeze({standby:"standby",outbound:"outbound"}),Xe=Object.freeze({keep:"keep",restartStandby:"restart_standby"}),Mi=new Set(["session_missing_or_terminal","session_binding_changed","session_anchor_changed","browser_lease_lost","anchor_or_browser_conflict"]);function qi(a,e){return e?`${a}
|
|
286
|
+
${JSON.stringify(e,null,2)}`:a}function Oi(a){if(typeof window>"u"||!a)return!1;try{return window.localStorage.getItem(a)==="1"}catch{return!1}}function Fi(a,e){if(!(typeof window>"u"||!a))try{e&&window.localStorage.setItem(a,"1")}catch{}}const Ni=`
|
|
287
|
+
<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">
|
|
288
|
+
<path d="M6.84 4.28c.3-.72 1.15-1.1 1.89-.85l2.24.75c.77.26 1.18 1.09.91 1.85l-.64 1.82a1.6 1.6 0 0 1-1.9.99l-.63-.16a12.8 12.8 0 0 0 6.62 6.62l-.16-.63a1.6 1.6 0 0 1 .99-1.9l1.82-.64c.76-.27 1.59.14 1.85.91l.75 2.24c.25.74-.13 1.59-.85 1.89l-1.74.72c-.72.3-1.54.26-2.23-.1A17.94 17.94 0 0 1 4.48 7.23c-.36-.69-.4-1.51-.1-2.23z" fill="currentColor"/>
|
|
289
|
+
</svg>
|
|
290
|
+
`;function A(a,e,t){t!=null&&(typeof t=="string"&&t.trim()===""||(a[e]=t))}function se(a){return typeof a=="string"?a.trim():""}function xt(a,e,t){const i=se(a?.session_mode);if(!i)throw L(`${t} 缺少必填字段 session_mode。`,{source:t,session_id:a?.session_id||null,expected_session_mode:e,received_session_mode:null});if(!Object.values(Ie).includes(i))throw L(`${t} 返回了未登记的 session_mode。`,{source:t,session_id:a?.session_id||null,expected_session_mode:e,received_session_mode:i});if(i!==e)throw L(`${t} 返回的 session_mode 与当前流程不匹配。`,{source:t,session_id:a?.session_id||null,expected_session_mode:e,received_session_mode:i});return i}function Ui(a,e={}){const t=se(e?.session_action).toLowerCase(),i=se(e?.session_action_reason)||null,s=se(e?.session_action_detail)||null,r=se(e?.resolved_session_id)||null,n=se(e?.resolved_widget_anchor_number)||null,o=se(e?.resolved_browser_sip_username)||null,d={source:a,session_action:t||null,session_action_reason:i,session_action_detail:s,resolved_session_id:r,resolved_widget_anchor_number:n,resolved_browser_sip_username:o};if(!t)throw L("服务端缺少必填字段 session_action。",d);if(!Object.values(Xe).includes(t))throw L("服务端返回了未登记的 session_action。",d);if(t===Xe.keep){if(i||s)throw L("session_action=keep 时不得携带 session_action_reason 或 session_action_detail。",d);return{action:t,reason:null,detail:null,resolvedSessionId:r,resolvedWidgetAnchorNumber:n,resolvedBrowserSipUsername:o}}if(!i)throw L("session_action=restart_standby 时必须携带 session_action_reason。",d);if(!Mi.has(i))throw L("服务端返回了未登记的 session_action_reason。",d);if(!s)throw L("session_action=restart_standby 时必须携带非空的 session_action_detail。",d);if(i==="session_missing_or_terminal"){if(r||n||o)throw L("session_missing_or_terminal 不得返回非空 resolved_* 字段。",d)}else if(i==="session_binding_changed"||i==="browser_lease_lost"){if(!r||!o)throw L(`${i} 必须返回 resolved_session_id 和 resolved_browser_sip_username。`,d)}else if(i==="session_anchor_changed"){if(!r||!n)throw L("session_anchor_changed 必须返回 resolved_session_id 和 resolved_widget_anchor_number。",d)}else if(i==="anchor_or_browser_conflict"&&(!r||!n&&!o))throw L("anchor_or_browser_conflict 必须返回 resolved_session_id 及至少一个冲突定位字段。",d);return{action:t,reason:i,detail:s,resolvedSessionId:r,resolvedWidgetAnchorNumber:n,resolvedBrowserSipUsername:o}}function Li(a){return a==="outbound"?"outbound":"terminal"}function Bi(a){return typeof a=="function"}function ji(){return typeof window>"u"?!1:new URLSearchParams(window.location.search).get("embeddedCallWidgetE2E")==="1"}function Vi(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`widget-${Date.now()}-${Math.random().toString(16).slice(2,10)}`}function Qe(a){const e=String(a?.message||a||"");return/Failed to fetch|NetworkError|Load failed|network/i.test(e)}function le(a={},e=null){const t=a?.advanced&&typeof a.advanced=="object"?a.advanced:{},i=String(t.visitorBusinessKey??"").trim();if(i)return i;const s=String(a?.businessKey??"").trim();return s||""}function Gi(a){const e=new Error(a);return e.name="EmbeddedCallWidgetLifecycleCancelledError",e.code="widget_runtime_run_stale",e}function _t(a){return a?.code==="sip_client_replaced"||a?.code==="widget_runtime_run_stale"}function L(a,e={}){const t=new Error(a);return t.name="EmbeddedCallWidgetProtocolViolationError",t.code="widget_protocol_violation",t.detail=e,t}function Oe(a){return a?.code==="widget_protocol_violation"}class Wi{constructor({mount:e,shadowRoot:t,options:i}){this.mountNode=e,this.shadowRoot=t,this.options=i,this.mode=Li(i.mode),this.legacyOutboundOnly=this.mode==="outbound",this.apiBaseUrl=_e(i.apiBaseUrl||window.location.origin).href,this.client=null,this.issuedSession=null,this.bootstrap=null,this.turnIceServers=[],this.state="idle",this.stateDetail=ie.idle,this.finalizing=!1,this.isMobileViewport=!1,this.pendingIncomingCall=null,this.visibilityHandler=null,this.sessionTouchTimer=null,this.sessionRecoveryInFlight=null,this.transportDisconnectTimer=null,this.transportDisconnectContext=null,this.e2eBridgeEnabled=ji(),this.terminalFailureOverride="",this.presenceId=Vi(),this.presenceTouchTimer=null,this.presenceFailureCount=0,this.availabilityState="preparing",this.availabilityDetail="正在连接后台并准备网页电话待机。",this.connectivityRecoveryInFlight=null,this.lifecycleRunId=0,this.pendingLifecycleMode=null,this.expectedClientTeardown=null,this.expectedTermination=null,this.autoStandbyRecoveryTimer=null,this.recentlyReleasedSessions=new Map,this.networkOnline=typeof navigator>"u"?!0:navigator.onLine!==!1,this.pageVisible=typeof document>"u"?!0:document.visibilityState==="visible",this.onlineHandler=null,this.offlineHandler=null,this.beforeUnloadHandler=null,this.pageHideHandler=null,this.unloadCleanupStarted=!1,this.panelAutoCloseTimer=null,this.transientPanelState=null,this.transientPanelDetail="",this.missedIncomingCount=0,this.debugRequested=i.debug===!0,this.debugPanelEnabled=!1,this.hasAccessToken=!!String(i.accessToken||"").trim(),this.triggerHintStorageKey=`${Hi}${String(i.siteKey||"default").trim()||"default"}`,this.triggerHintDismissed=Oi(this.triggerHintStorageKey),this.refs={}}async mount(){this.isMobileViewport=typeof window<"u"&&window.matchMedia("(max-width: 480px)").matches,this.shadowRoot.innerHTML=`
|
|
104
291
|
<style>${_i}</style>
|
|
105
292
|
<section class="widget">
|
|
106
|
-
<
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
293
|
+
<button class="trigger" data-role="trigger" type="button" aria-label="${this.options.text||"联系管理员"}">
|
|
294
|
+
${Ni}
|
|
295
|
+
<span class="trigger-badge" data-role="trigger-badge" hidden></span>
|
|
296
|
+
<span class="sr-only">${this.options.text||"联系管理员"}</span>
|
|
297
|
+
</button>
|
|
298
|
+
<div class="panel-shell" data-role="panel-shell">
|
|
299
|
+
<div class="panel-backdrop" data-role="backdrop"></div>
|
|
300
|
+
<section class="panel" data-role="panel" aria-live="polite" aria-modal="false">
|
|
301
|
+
<div class="panel-hero">
|
|
302
|
+
<p class="panel-eyebrow" data-role="panel-eyebrow">网页通话</p>
|
|
303
|
+
<h2 class="panel-title" data-role="panel-title">${this.options.text||"联系管理员"}</h2>
|
|
304
|
+
<div class="status" data-role="status">${Ze.idle}</div>
|
|
305
|
+
<div class="panel-detail" data-role="panel-detail"></div>
|
|
306
|
+
</div>
|
|
307
|
+
<div class="actions" data-role="actions">
|
|
308
|
+
<button class="btn btn-primary" data-role="primary" type="button" hidden></button>
|
|
309
|
+
<button class="btn btn-secondary" data-role="secondary" type="button" hidden></button>
|
|
310
|
+
</div>
|
|
311
|
+
</section>
|
|
121
312
|
</div>
|
|
313
|
+
<section class="debug-panel" data-role="debug-panel" hidden>
|
|
314
|
+
<div class="availability availability--preparing" data-role="availability">正在准备</div>
|
|
315
|
+
<div class="meta" data-role="meta">站点键:${this.options.siteKey||"等待服务端解析"};访客主动呼叫默认规则:${le(this.options)||"等待服务端解析"}</div>
|
|
316
|
+
<div class="hint" data-role="hint"></div>
|
|
317
|
+
<div class="logs" data-role="logs"></div>
|
|
318
|
+
</section>
|
|
319
|
+
<audio class="audio" data-role="audio" autoplay playsinline></audio>
|
|
122
320
|
</section>
|
|
123
|
-
`,this.refs.status=this.shadowRoot.querySelector('[data-role="status"]'),this.refs.availability=this.shadowRoot.querySelector('[data-role="availability"]'),this.refs.hint=this.shadowRoot.querySelector('[data-role="hint"]'),this.refs.meta=this.shadowRoot.querySelector('[data-role="meta"]'),this.refs.primary=this.shadowRoot.querySelector('[data-role="primary"]'),this.refs.secondary=this.shadowRoot.querySelector('[data-role="secondary"]'),this.refs.logs=this.shadowRoot.querySelector('[data-role="logs"]'),this.refs.audio=this.shadowRoot.querySelector('[data-role="audio"]'),this.refs.primary.addEventListener("click",()=>{this.handlePrimaryAction()}),this.refs.secondary.addEventListener("click",()=>{this.handleSecondaryAction()}),this.bindPageLifecycle(),this.registerE2EBridge(),this.startPresenceTouch(),this.render()}bindPageLifecycle(){typeof document>"u"||(this.visibilityHandler=()=>{if(this.pageVisible=document.visibilityState==="visible",document.visibilityState==="hidden"){this.reportIssuedSessionEvent("visibility-hidden",{visible:!1}),this.touchWidgetPresence("visibility-hidden"),this.issuedSession?.session_id&&this.touchIssuedSession(this.state,{trigger:"visibility-hidden"}),this.appendLog("页面已切到后台",{state:this.state,advice:"系统会继续自动保活;回到前台后请确认页面仍保持活动。"}),this.isMobileViewport&&["requesting","registering","calling","connected"].includes(this.state)&&(this.refs.status.textContent="页面已切到后台;手机网页回到前台后请确认通话仍在继续。");return}if(this.isMobileViewport&&(this.appendLog("页面已回到前台",{state:this.state}),["requesting","registering","calling","connected"].includes(this.state)&&(this.refs.status.textContent=te[this.state]||te.idle)),this.touchWidgetPresence("visibility-visible"),!this.legacyOutboundOnly&&["standby","registering","standbyRequesting","failed","idle","missed","rejected","ended"].includes(this.state)){const e=this.client?.getConnectionSnapshot?.()||null,t=!!(e?.connected&&(this.state!=="standby"||e?.registered));this.issuedSession?.session_id&&t?this.touchIssuedSession(this.state,{trigger:"visibility-visible"}):(this.appendLog("页面回到前台后检测到待机链路未处于健康状态,准备自动重建。",{state:this.state,has_session:!!this.issuedSession?.session_id,client_snapshot:e}),this.client||this.issuedSession?.session_id?this.disconnectAndCleanup("visibility-visible-unhealthy-client"):this.startStandby({force:!0}))}this.reportIssuedSessionEvent("visibility-visible",{visible:!0}),this.render()},document.addEventListener("visibilitychange",this.visibilityHandler),typeof window<"u"&&(this.onlineHandler=()=>{this.networkOnline=!0,this.setAvailabilityState("recovering","网络已恢复,正在重新连接网页电话。"),this.touchWidgetPresence("browser-online"),this.legacyOutboundOnly||this.restartStandbyAfterConnectivity("browser-online")},this.offlineHandler=()=>{this.networkOnline=!1,this.setAvailabilityState("offline","当前网络连接已断开,正在等待恢复。"),["incoming","connected"].includes(this.state)?this.render():this.setState("failed","当前网络连接已断开,正在等待恢复。")},window.addEventListener("online",this.onlineHandler),window.addEventListener("offline",this.offlineHandler),this.beforeUnloadHandler=()=>{this.flushUnloadCleanup("beforeunload")},this.pageHideHandler=e=>{e?.persisted||this.flushUnloadCleanup("pagehide")},window.addEventListener("beforeunload",this.beforeUnloadHandler),window.addEventListener("pagehide",this.pageHideHandler)))}open(){this.mountNode.scrollIntoView({block:"nearest",inline:"nearest"})}beginLifecycleRun(){return this.lifecycleRunId+=1,this.lifecycleRunId}assertLifecycleRunCurrent(e){if(e!==this.lifecycleRunId)throw Ni("网页电话已切换到新的连接流程,旧流程不再继续。")}emitHostCallback(e,t){const i=this.options?.[e];if(qi(i))try{i(t)}catch(s){this.appendLog("宿主回调执行失败",{callback:e,message:s?.message||String(s)})}}getSnapshot(){return{mode:this.mode,state:this.state,sessionMode:this.issuedSession?.session_mode||null,sessionId:this.issuedSession?.session_id||null,siteKey:this.options.siteKey||this.bootstrap?.default_site_key||null,businessKey:this.issuedSession?.resolved_business_key||ce(this.options,this.bootstrap)||null,standbyMode:this.issuedSession?.standby_mode||null,standbyState:this.issuedSession?.standby_state||this.options.standbyState||null,widgetSipNumber:this.issuedSession?.widget_anchor_number||null,browserSipUsername:this.issuedSession?.browser_sip_username||this.issuedSession?.sip_username||null,routeNote:this.issuedSession?.route_note||null,incomingAnchors:Array.isArray(this.issuedSession?.incoming_anchors)?this.issuedSession.incoming_anchors:[],hasClient:!!this.client,hasIssuedSession:!!this.issuedSession?.session_id,primaryText:this.refs.primary?.textContent?.trim()||"",secondaryText:this.refs.secondary?.textContent?.trim()||"",statusText:this.refs.status?.textContent?.trim()||"",availabilityState:this.availabilityState,availabilityLabel:this.refs.availability?.textContent?.trim()||"",presenceId:this.presenceId,networkOnline:this.networkOnline,pendingIncomingCall:this.pendingIncomingCall}}registerE2EBridge(){if(!this.e2eBridgeEnabled||typeof window>"u")return;const e=window.location.hostname||"example.invalid";window.__embeddedCallWidgetE2E__={getSnapshot:()=>this.getSnapshot(),simulateIncomingCall:(t={})=>{const i=t.host||e,s=t.user||"2001";return this.pendingIncomingCall={displayName:t.displayName||"测试来电",user:s,host:i,direction:"inbound",uri:t.uri||`sip:${s}@${i}`,e2eSimulated:!0},this.setState("incoming"),this.emitHostCallback("onIncomingCall",this.pendingIncomingCall),this.getSnapshot()},answerIncomingCall:async()=>(await this.answerIncomingCall(),this.getSnapshot()),declineIncomingCall:async()=>(await this.declineIncomingCall(),this.getSnapshot()),hangupCall:async()=>(await this.hangupCall(),this.getSnapshot()),destroyWidget:async()=>(await this.destroy(),null)}}async handlePrimaryAction(){if(this.availabilityState==="offline"){const e=this.networkOnline===!1?"当前网络连接已断开,正在尝试恢复,请稍后再试。":"当前无法连接通话服务,正在尝试恢复,请稍后再试。";this.appendLog("访客点击了离线中的 widget",{state:this.state,availability:this.availabilityState,message:e}),["incoming","connected"].includes(this.state)||this.setState("failed",e),this.render();return}if(this.state==="incoming"){await this.answerIncomingCall();return}if(this.legacyOutboundOnly){await this.connectAndCall();return}if(!this.client&&!this.issuedSession){await this.startStandby();return}await this.connectAndCall()}async handleSecondaryAction(){if(this.state==="incoming"){await this.declineIncomingCall();return}if(this.state==="connected"&&this.client){await this.hangupCall();return}await this.disconnectAndCleanup("manual-disconnect")}async connectAndCall(){if(["requesting","registering","calling","connected"].includes(this.state))return;const e=this.beginLifecycleRun();try{this.terminalFailureOverride="",this.clearAutoStandbyRecovery(),this.pendingLifecycleMode="outbound",this.setAvailabilityState("working","正在建立呼叫链路。");const t=this.issuedSession?.session_mode==="widget_standby"&&(this.issuedSession?.browser_sip_username||this.issuedSession?.sip_username)||null;!this.legacyOutboundOnly&&this.issuedSession?.session_mode==="widget_standby"&&(this.appendLog("访客主动呼叫前,先释放当前待机会话并切换到呼叫链路。",{widget_anchor_number:this.issuedSession?.widget_anchor_number||null,resolved_business_key:this.issuedSession?.resolved_business_key||ce(this.options)||null}),await this.disconnectAndCleanup("switch-to-outbound-call",{preserveLifecycleRun:!0,suppressStateReset:!0,suppressClientTeardownState:"switch-to-outbound-call"}),this.assertLifecycleRunCurrent(e)),this.setState("requesting"),await this.loadBootstrap(),this.assertLifecycleRunCurrent(e),this.turnIceServers=await this.fetchTurnIceServers(),this.assertLifecycleRunCurrent(e);const i=await this.fetchIssuedSession({preferredBrowserSipUsername:t});this.assertLifecycleRunCurrent(e),await this.ensureClient(i),this.assertLifecycleRunCurrent(e),this.setState("registering"),await this.client.ensureReady(),this.assertLifecycleRunCurrent(e),this.setState("calling"),this.syncAvailabilityState(),await this.client.call(i.target),this.assertLifecycleRunCurrent(e),this.appendLog("已发起呼叫",{target:i.target,route_note:i.routeNote||null})}catch(t){if(this.pendingLifecycleMode=null,_t(t)){this.appendLog("已忽略过期的网页电话呼叫流程",{message:t?.message||String(t)});return}if(Oe(t)){await this.handleProtocolViolation(t);return}const i=t?.message||String(t);if(this.terminalFailureOverride=i,this.setState("failed",i),Xe(t)||this.networkOnline===!1?this.setAvailabilityState("offline",this.networkOnline===!1?"当前网络连接已断开,正在等待恢复。":"当前无法连接通话服务,正在自动尝试恢复。"):this.setAvailabilityState("recovering","呼叫失败,正在准备恢复网页电话待机。"),this.appendLog("连接并呼叫失败",{message:i}),await this.releaseIssuedSession("failed","connect-and-call-failed"),!this.legacyOutboundOnly){this.appendLog("呼叫失败后,网页电话将恢复待机。",{message:i}),await this.startStandby({force:!0});return}this.setState("failed",i)}}async startStandby(e={}){if(this.legacyOutboundOnly)throw new Error("当前 widget 仍处于 legacy outbound 兼容模式");const{force:t=!1}=e;if(!t&&["standbyRequesting","registering","incoming","connected"].includes(this.state))return;const i=this.beginLifecycleRun();try{this.clearAutoStandbyRecovery(),this.pendingLifecycleMode="standby",this.terminalFailureOverride="",this.setState("standbyRequesting"),this.setAvailabilityState("preparing","正在申请新的待机会话。"),await this.loadBootstrap(),this.assertLifecycleRunCurrent(i),this.turnIceServers=await this.fetchTurnIceServers(),this.assertLifecycleRunCurrent(i);const s=await this.fetchStandbySession();this.assertLifecycleRunCurrent(i),await this.ensureClient(s),this.assertLifecycleRunCurrent(i),this.setState("registering","待机会话已拿到,正在连接并执行 REGISTER。"),await this.client.ensureReady(),this.assertLifecycleRunCurrent(i),this.pendingLifecycleMode=null,this.setState("standby"),this.setAvailabilityState("ready","当前可被呼叫,也可由访客主动发起呼叫。"),this.appendLog("widget 已进入待机",{session_id:this.issuedSession?.session_id||null,route_business_key:this.issuedSession?.resolved_business_key||ce(this.options)||null,standby_mode:this.issuedSession?.standby_mode||null,widget_anchor_number:this.issuedSession?.widget_anchor_number||null,browser_sip_username:this.issuedSession?.browser_sip_username||this.issuedSession?.sip_username||null}),this.emitHostCallback("onStandbyReady",this.getSnapshot())}catch(s){if(_t(s)){this.appendLog("已忽略过期的网页电话待机流程",{message:s?.message||String(s)});return}if(this.pendingLifecycleMode=null,Oe(s)){await this.handleProtocolViolation(s);return}const r=s?.message||String(s);this.terminalFailureOverride=r,this.setState("failed",r),Xe(s)||this.networkOnline===!1?this.setAvailabilityState("offline",this.networkOnline===!1?"当前网络连接已断开,正在等待恢复。":"当前无法连接通话服务,正在自动尝试恢复。"):this.setAvailabilityState("recovering","当前未能完成待机注册,系统会继续自动恢复。"),this.appendLog("进入待机失败",{message:r}),await this.releaseIssuedSession("failed","standby-start-failed"),this.setState("failed",r),!this.legacyOutboundOnly&&this.networkOnline!==!1&&this.scheduleAutoStandbyRecovery("standby-start-failed")}}async ensureClient(e){const t={sip_username:e.sipUsername,sip_password:e.password,sip_domain:e.sipDomain,webrtc_url:e.transport,ice_servers:this.turnIceServers};this.client?.matchesAccount(t)||(this.client&&await this.client.destroy(),this.client=new vi(t,{remoteAudioElement:this.refs.audio,onStateChange:(i,s)=>{this.handleClientState(i,s)},onError:i=>this.appendLog("SIP 客户端错误",{message:i?.message||String(i)})}))}async handleClientState(e,t={}){if(this.syncSessionTouch(e),this.reportIssuedSessionEvent(e,t,e),(e==="connected"||e==="registered"||e==="ringing"||e==="dialing"||e==="answered")&&await this.clearTransportDisconnectGrace(!0),e==="registered"){this.pendingLifecycleMode=null,this.issuedSession?.session_mode==="widget_standby"?(this.setState("standby"),this.setAvailabilityState("ready","当前可被呼叫,也可由访客主动发起呼叫。")):this.setState("registering","REGISTER 已完成,正在准备发起呼叫。");return}if(e==="incoming"){this.pendingLifecycleMode=null,this.pendingIncomingCall=t&&typeof t=="object"?{...t}:null,this.setState("incoming"),this.setAvailabilityState("working","已有新来电,请直接接听或拒接。"),this.appendLog("收到新的来电",this.pendingIncomingCall),this.emitHostCallback("onIncomingCall",this.pendingIncomingCall);return}if(e==="ringing"||e==="dialing"){this.setState("calling",t?.message||te.calling);return}if(e==="answered"){this.pendingLifecycleMode=null,this.terminalFailureOverride="";const i=this.pendingIncomingCall||t||null;this.setState("connected"),this.setAvailabilityState("working","当前通话已接通。"),this.emitHostCallback("onCallAnswered",i);return}if(e==="terminated"){if(this.issuedSession?.session_mode==="widget_standby"){await this.handleStandbyTermination(t);return}t&&typeof t=="object"&&(t.source==="invite-response"||t.source==="invite-exception"||t.code||t.status||t.stage)&&(this.terminalFailureOverride=t?.message||te.failed,this.setState("failed",this.terminalFailureOverride)),await this.finalizeAfterTermination(t?.hangupSource||"terminated");return}if(e==="failed"){if(this.isExpectedClientTeardown())return;this.pendingLifecycleMode=null,await this.clearTransportDisconnectGrace(!1),this.stopSessionTouch(),this.terminalFailureOverride=t?.message||te.failed,this.setState("failed",this.terminalFailureOverride),this.setAvailabilityState("recovering","通话链路异常断开,系统会继续自动恢复。"),await this.releaseIssuedSession("failed","sip-client-failed");return}if(e==="disconnected"||e==="unregistered"){if(this.isExpectedClientTeardown()||this.isExpectedTermination()||!this.issuedSession?.session_id&&this.pendingLifecycleMode==="standby")return;if(this.stopSessionTouch(),["calling","connected"].includes(this.state)){this.setState("connected","SIP 信令短暂中断,正在等待恢复。"),this.setAvailabilityState("recovering","通话信令短暂中断,正在等待恢复。"),this.scheduleTransportDisconnectGrace(e);return}const s=this.terminalFailureOverride||this.client?.lastFailureMeta?.message||null;if(s){this.terminalFailureOverride=s,this.setState("failed",s);return}if(this.state==="failed")return;this.state!=="idle"&&this.state!=="ended"&&(this.pendingLifecycleMode=null,this.setState("ended"),this.setAvailabilityState("preparing","通话已结束,正在自动返回网页电话待机。"),this.scheduleAutoStandbyRecovery(`client-${e}`))}}stopTransportDisconnectGrace(){this.transportDisconnectTimer&&(window.clearTimeout(this.transportDisconnectTimer),this.transportDisconnectTimer=null),this.transportDisconnectContext=null}sameTransportDisconnectContext(e){return!e||!this.issuedSession?.session_id?!1:e.sessionId===this.issuedSession.session_id}async clearTransportDisconnectGrace(e){const t=this.transportDisconnectContext,i=!!(e&&t?.reported&&this.sameTransportDisconnectContext(t));this.stopTransportDisconnectGrace(),i&&(await this.reportIssuedSessionEvent("transport-restored",{disconnectDurationMs:Date.now()-(t.startedAt||Date.now()),graceMs:Re},this.state),this.appendLog("网页通话信令已恢复",{disconnectDurationMs:Date.now()-(t.startedAt||Date.now()),graceMs:Re}))}scheduleTransportDisconnectGrace(e){if(!this.issuedSession?.session_id)return;this.stopTransportDisconnectGrace();const t={sessionId:this.issuedSession.session_id,startedAt:Date.now(),reported:!1,state:e};this.transportDisconnectContext=t,this.transportDisconnectTimer=window.setTimeout(()=>{this.transportDisconnectTimer=null,this.sameTransportDisconnectContext(t)&&(t.reported=!0,this.reportIssuedSessionEvent("transport-disconnected",{state:e,graceMs:Re},this.state),this.appendLog("网页通话信令断开超过宽限窗口",{graceMs:Re,state:e}))},Re)}async finalizeAfterTermination(e){if(!this.finalizing){this.beginLifecycleRun(),this.finalizing=!0;try{if(this.pendingLifecycleMode=null,this.stopSessionTouch(),this.stopTransportDisconnectGrace(),await this.releaseIssuedSession("released",e),this.client&&(await this.client.destroy(),this.client=null),!this.legacyOutboundOnly){this.pendingLifecycleMode="standby",this.setState("standbyRequesting","上一通通话已结束,正在自动回到待机。"),this.setAvailabilityState("preparing","页面仍在线,正在自动回到待机。"),this.appendLog("通话已结束,网页电话正在自动回到待机。",{reason:e}),await this.startStandby({force:!0});return}const t=this.terminalFailureOverride||(this.state==="failed"?this.refs.status?.textContent?.trim()||te.failed:"");t?this.setState("failed",t):this.setState("ended"),this.appendLog("通话已结束并完成清理",{reason:e})}finally{this.finalizing=!1}}}async handleStandbyTermination(e={}){this.stopTransportDisconnectGrace();const t=this.state,i=e?.hangupSource||"terminated";t==="incoming"?i==="local"?(this.setState("rejected"),this.setAvailabilityState("ready","当前来电已拒接,widget 仍保持可用。"),this.emitHostCallback("onCallRejected",this.pendingIncomingCall||e||null)):(this.setState("missed"),this.setAvailabilityState("ready","当前来电未接听,widget 仍保持可用。"),this.emitHostCallback("onCallMissed",this.pendingIncomingCall||e||null)):(this.setState("standby","上一通来电已结束,继续等待下一通来电。"),this.setAvailabilityState("ready","当前可被呼叫,也可由访客主动发起呼叫。")),this.appendLog("待机会话中的来电已结束",{hangupSource:i,previousState:t}),this.pendingIncomingCall=null}async answerIncomingCall(){if(this.state==="incoming"){if(this.e2eBridgeEnabled&&this.pendingIncomingCall?.e2eSimulated){this.setState("connected","测试桥已模拟接听当前来电。"),this.emitHostCallback("onCallAnswered",this.pendingIncomingCall);return}if(!this.client&&this.e2eBridgeEnabled){this.setState("connected","测试桥已模拟接听当前来电。"),this.emitHostCallback("onCallAnswered",this.pendingIncomingCall);return}if(!this.client)throw new Error("当前没有可接听的 SIP 会话");await this.client.answer()}}async declineIncomingCall(){if(this.state==="incoming"){if(this.e2eBridgeEnabled&&this.pendingIncomingCall?.e2eSimulated){this.setState("rejected"),this.emitHostCallback("onCallRejected",this.pendingIncomingCall),this.pendingIncomingCall=null;return}if(!this.client&&this.e2eBridgeEnabled){this.setState("rejected"),this.emitHostCallback("onCallRejected",this.pendingIncomingCall),this.pendingIncomingCall=null;return}if(!this.client)throw new Error("当前没有可拒接的 SIP 会话");await this.client.decline()}}async hangupCall(){if(this.e2eBridgeEnabled&&this.pendingIncomingCall?.e2eSimulated){this.legacyOutboundOnly?this.setState("ended"):this.setState("standby","测试桥已模拟挂断,网页电话已恢复待机。"),this.pendingIncomingCall=null;return}if(!this.client&&this.e2eBridgeEnabled){this.legacyOutboundOnly?this.setState("ended"):this.setState("standby","测试桥已模拟挂断,网页电话已恢复待机。"),this.pendingIncomingCall=null;return}this.client&&(this.expectTermination("hangup-call"),this.suppressExpectedClientTeardown("hangup-call"),await this.client.hangup())}async disconnectAndCleanup(e,t={}){const{preserveLifecycleRun:i=!1,suppressStateReset:s=!1,suppressClientTeardownState:r=null}=t;i||this.beginLifecycleRun(),r&&this.suppressExpectedClientTeardown(r),this.stopSessionTouch(),this.stopTransportDisconnectGrace(),this.reportIssuedSessionEvent("manual-disconnect",{reason:e},this.state),this.pendingIncomingCall=null,this.terminalFailureOverride="",this.client&&(await this.client.destroy(),this.client=null),await this.releaseIssuedSession("released",e),s||(this.pendingLifecycleMode=null,this.setState("idle"),this.setAvailabilityState("preparing","网页电话已断开,系统正在自动返回待机。"),this.appendLog("连接已断开",{reason:e}),!this.legacyOutboundOnly&&this.networkOnline!==!1&&this.scheduleAutoStandbyRecovery(e))}async loadBootstrap(){if(this.bootstrap)return this.bootstrap;const e=await fetch(X(this.apiBaseUrl,"api/sip/embedded-call-demo-bootstrap"),{credentials:"include",cache:"no-store"});if(!e.ok)throw new Error(`默认模式读取失败:${e.status}`);return this.bootstrap=await e.json(),this.bootstrap}async fetchTurnIceServers(){const e=await fetch(X(this.apiBaseUrl,"api/sip/webrtc-turn-credentials"),{credentials:"include",cache:"no-store"});if(!e.ok)return this.appendLog("TURN 凭证获取失败,继续尝试直连",{status:e.status}),[];const t=await e.json();return Array.isArray(t?.ice_servers)?t.ice_servers:[]}async fetchIssuedSession(e={}){const{preferredBrowserSipUsername:t=null}=e,i=ce(this.options),s={page_url:window.location.href};A(s,"site_key",this.options.siteKey),A(s,"standby_state",this.options.standbyState),A(s,"selected_primary_account",this.options.selectedPrimaryAccount),A(s,"selected_middle_layer_account",this.options.selectedMiddleLayerAccount),A(s,"preferred_browser_sip_username",t),A(s,"display_name",this.options.displayName),A(s,"access_token",this.options.accessToken),i&&(s.business_key=i);const r=await fetch(X(this.apiBaseUrl,"api/sip/issue-call-session"),{method:"POST",credentials:"include",cache:"no-store",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!r.ok){const d=await r.json().catch(()=>({}));throw new Error(d?.detail||`会话签发失败:${r.status}`)}const n=await r.json(),a=Et(n,xe.outbound,"issue-call-session");return this.issuedSession=n,this.reportIssuedSessionEvent("issued-session-fetched",{sessionId:n.session_id,targetExtension:n.target_extension,dialTargetExtension:n.dial_target_extension||n.target_extension,resolvedTargetInternalNumbers:n.resolved_target_internal_numbers||[],resolvedBusinessKey:n.resolved_business_key||null},"requesting"),this.appendLog("已获取服务端签发会话",{session_id:n.session_id,target_extension:n.target_extension,dial_target_extension:n.dial_target_extension||n.target_extension||null,resolved_target_internal_numbers:n.resolved_target_internal_numbers||[],resolved_business_key:n.resolved_business_key||null,resolved_route_mode:n.resolved_route_mode||null,route_note:n.route_note||null}),{sessionMode:a,sipUsername:n.sip_username,sipDomain:n.sip_domain,password:n.sip_password,transport:St({apiBaseUrl:this.apiBaseUrl,transportBaseUrl:this.options.transportBaseUrl||"",transportUrl:n.ws_server}),target:n.dial_target_extension||n.target_extension,routeNote:n.route_note||""}}async fetchStandbySession(){const e=ce(this.options)||null,t={page_url:window.location.href};A(t,"site_key",this.options.siteKey),A(t,"standby_state",this.options.standbyState),A(t,"selected_primary_account",this.options.selectedPrimaryAccount),A(t,"selected_middle_layer_account",this.options.selectedMiddleLayerAccount),A(t,"display_name",this.options.displayName),A(t,"access_token",this.options.accessToken),e&&(t.business_key=e);const i=await fetch(X(this.apiBaseUrl,"api/sip/issue-widget-standby-session"),{method:"POST",credentials:"include",cache:"no-store",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!i.ok){const n=await i.json().catch(()=>({}));throw new Error(n?.detail||`待机会话签发失败:${i.status}`)}const s=await i.json(),r=Et(s,xe.standby,"issue-widget-standby-session");return this.issuedSession=s,this.reportIssuedSessionEvent("standby-session-fetched",{sessionId:s.session_id,resolvedBusinessKey:s.resolved_business_key||null,standbyMode:s.standby_mode||null},"standbyRequesting"),this.appendLog("已获取 widget 待机会话",{session_id:s.session_id,resolved_business_key:s.resolved_business_key||null,standby_mode:s.standby_mode||null,standby_state:s.standby_state||null,widget_anchor_number:s.widget_anchor_number||null,browser_sip_username:s.browser_sip_username||s.sip_username||null,route_note:s.route_note||null}),{sessionMode:r,sipUsername:s.sip_username,sipDomain:s.sip_domain,password:s.sip_password,transport:St({apiBaseUrl:this.apiBaseUrl,transportBaseUrl:this.options.transportBaseUrl||"",transportUrl:s.ws_server}),target:null,routeNote:s.route_note||""}}async releaseIssuedSession(e,t){if(!this.issuedSession?.session_id)return;const i=this.issuedSession.session_id;this.markRecentlyReleasedSession(i,t),this.issuedSession=null,await fetch(X(this.apiBaseUrl,"api/sip/release-call-session"),{method:"POST",credentials:"include",cache:"no-store",headers:{"Content-Type":"application/json"},body:JSON.stringify({session_id:i,status:e,reason:t,client_summary:this.buildClientEvidenceSummary(e,{releaseReason:t})})}).catch(()=>{})}postLifecycleBeacon(e,t){const i=JSON.stringify(t),s=X(this.apiBaseUrl,e);if(typeof navigator<"u"&&typeof navigator.sendBeacon=="function")try{const r=new Blob([i],{type:"application/json"});if(navigator.sendBeacon(s,r))return!0}catch{}return fetch(s,{method:"POST",credentials:"include",cache:"no-store",keepalive:!0,headers:{"Content-Type":"application/json"},body:i}).catch(()=>{}),!0}flushUnloadCleanup(e){if(this.unloadCleanupStarted||(this.unloadCleanupStarted=!0,this.stopSessionTouch(),this.stopPresenceTouch(),this.stopTransportDisconnectGrace(),!this.issuedSession?.session_id))return;const t=this.issuedSession.session_id;this.markRecentlyReleasedSession(t,e),this.postLifecycleBeacon("api/sip/release-call-session",{session_id:t,status:"released",reason:e,client_summary:this.buildClientEvidenceSummary("released",{releaseReason:e})}),this.issuedSession=null}buildClientEvidenceSummary(e=null,t=null){const i={runtimeMode:"embedded-widget-runtime",widgetVersion:"2026-03-29-runtime-evidence",widgetMode:this.mode,sessionMode:this.issuedSession?.session_mode||null,state:e||this.state,visible:typeof document>"u"?!0:document.visibilityState==="visible",pageUrl:typeof window>"u"?null:window.location.href,connectionSnapshot:this.client?.getConnectionSnapshot?.()||null};return t&&typeof t=="object"&&(i.eventDetail=t),i}buildPresenceEvidenceSummary(e=null,t=null){return{...this.buildClientEvidenceSummary(e,t),presenceId:this.presenceId,availabilityState:this.availabilityState,availabilityDetail:this.availabilityDetail,networkOnline:this.networkOnline,pageVisible:this.pageVisible}}setAvailabilityState(e,t=""){this.availabilityState=e,this.availabilityDetail=t||this.availabilityDetail,this.refs.availability&&(this.refs.availability.textContent=t?`${qe[e]||qe.recovering} · ${t}`:qe[e]||qe.recovering,this.refs.availability.className=`availability availability--${e}`),this.render()}suppressExpectedClientTeardown(e,t=Di){this.expectedClientTeardown={reason:e,expiresAt:Date.now()+t}}expectTermination(e,t=1e4){this.expectedTermination={reason:e,expiresAt:Date.now()+t}}clearExpectedTermination(){this.expectedTermination=null}isExpectedTermination(){const e=this.expectedTermination;return e?e.expiresAt<=Date.now()?(this.expectedTermination=null,!1):!0:!1}isExpectedClientTeardown(){const e=this.expectedClientTeardown;return e?e.expiresAt<=Date.now()?(this.expectedClientTeardown=null,!1):!0:!1}clearAutoStandbyRecovery(){this.autoStandbyRecoveryTimer&&(window.clearTimeout(this.autoStandbyRecoveryTimer),this.autoStandbyRecoveryTimer=null)}scheduleAutoStandbyRecovery(e,t=Ai){this.legacyOutboundOnly||this.networkOnline===!1||this.autoStandbyRecoveryTimer||this.client||this.issuedSession?.session_id||this.finalizing||this.pendingLifecycleMode==="outbound"||this.sessionRecoveryInFlight||this.connectivityRecoveryInFlight||["requesting","standbyRequesting","registering","calling","incoming","connected"].includes(this.state)||(this.autoStandbyRecoveryTimer=window.setTimeout(()=>{this.autoStandbyRecoveryTimer=null,!(this.legacyOutboundOnly||this.networkOnline===!1)&&(this.client||this.issuedSession?.session_id||this.finalizing||this.pendingLifecycleMode==="outbound"||(this.appendLog("检测到页面当前不在通话中,开始自动进入待机。",{reason:e}),this.startStandby({force:!0})))},t))}pruneRecentlyReleasedSessions(){const e=Date.now();for(const[t,i]of this.recentlyReleasedSessions.entries())(i?.expiresAt||0)<=e&&this.recentlyReleasedSessions.delete(t)}markRecentlyReleasedSession(e,t){e&&(this.pruneRecentlyReleasedSessions(),this.recentlyReleasedSessions.set(e,{reason:t,expiresAt:Date.now()+$i}))}wasSessionRecentlyReleased(e){return e?(this.pruneRecentlyReleasedSessions(),this.recentlyReleasedSessions.has(e)):!1}syncAvailabilityState(){if(this.networkOnline===!1){this.setAvailabilityState("offline","当前网络连接已断开,正在等待恢复。");return}if(this.state==="incoming"){this.setAvailabilityState("working","已有新来电,请直接接听或拒接。");return}if(this.state==="connected"){this.setAvailabilityState("working","当前通话已接通。");return}if(this.state==="calling"){this.setAvailabilityState("working","正在等待对端振铃或接听。");return}if(this.pendingLifecycleMode==="outbound"&&["requesting","registering"].includes(this.state)){this.setAvailabilityState("working","正在建立呼叫链路。");return}if(["requesting","standbyRequesting","registering"].includes(this.state)){this.setAvailabilityState("preparing","页面仍在线,正在建立网页电话连接。");return}if(!this.legacyOutboundOnly&&!this.issuedSession?.session_id&&!this.pendingLifecycleMode&&["idle","ended","missed","rejected"].includes(this.state)){this.setAvailabilityState("preparing","页面仍在线,正在自动进入网页电话待机。"),this.scheduleAutoStandbyRecovery("missing-issued-session");return}if(!this.legacyOutboundOnly&&!this.issuedSession?.session_id&&!this.pendingLifecycleMode&&!["calling","connected","incoming"].includes(this.state)){this.setAvailabilityState("preparing","页面仍在线,正在重新建立网页电话待机。"),this.scheduleAutoStandbyRecovery("missing-issued-session");return}this.setAvailabilityState("ready","当前可被呼叫,也可由访客主动发起呼叫。")}stopPresenceTouch(){this.presenceTouchTimer&&(window.clearInterval(this.presenceTouchTimer),this.presenceTouchTimer=null)}async restartStandbyAfterConnectivity(e){if(!(this.legacyOutboundOnly||this.connectivityRecoveryInFlight)&&!["connected","incoming","calling","requesting","standbyRequesting","registering"].includes(this.state)){this.connectivityRecoveryInFlight=(async()=>{this.appendLog("检测到连通性已恢复,准备重建网页电话待机。",{trigger:e,state:this.state,hasSession:!!this.issuedSession?.session_id}),(this.client||this.issuedSession?.session_id)&&await this.disconnectAndCleanup(`connectivity-restored-${e}`),await this.startStandby({force:!0})})();try{await this.connectivityRecoveryInFlight}finally{this.connectivityRecoveryInFlight=null}}}async handleServerSessionAction(e,t={}){if(this.legacyOutboundOnly)return!1;const i=Hi(e,t);if(i.action!==Ze.restartStandby)return!1;const s=ie(this.issuedSession?.session_mode),r=ie(this.pendingLifecycleMode),n=s===xe.outbound||r===Ct.outbound,a=s===xe.standby||r===Ct.standby;if(n||!a)throw L("非待机协议上下文收到了非法的 restart_standby 指令。",{source:e,state:this.state,local_session_mode:s||null,local_lifecycle_mode:r||null,session_action:i.action,session_action_reason:i.reason,session_action_detail:i.detail,resolved_session_id:i.resolvedSessionId,resolved_widget_anchor_number:i.resolvedWidgetAnchorNumber,resolved_browser_sip_username:i.resolvedBrowserSipUsername});if(this.sessionRecoveryInFlight||this.connectivityRecoveryInFlight)return!1;this.sessionRecoveryInFlight=(async()=>{this.appendLog("服务端要求当前页面立即放弃旧锚点并重建待机。",{source:e,state:this.state,local_session_mode:s||null,local_lifecycle_mode:r||null,session_action_reason:i.reason,session_action_detail:i.detail,resolved_session_id:i.resolvedSessionId,resolved_widget_anchor_number:i.resolvedWidgetAnchorNumber,resolved_browser_sip_username:i.resolvedBrowserSipUsername}),this.setAvailabilityState("recovering",i.detail||"当前锚点已失效,正在自动切换到新的待机线路。"),(this.client||this.issuedSession?.session_id)&&await this.disconnectAndCleanup(`server-session-action-${i.reason||e}`,{preserveLifecycleRun:!0,suppressStateReset:!0}),await this.startStandby({force:!0})})();try{await this.sessionRecoveryInFlight}finally{this.sessionRecoveryInFlight=null}return!0}async handleProtocolViolation(e){const t=e?.detail&&typeof e.detail=="object"?e.detail:{},i={violation_code:e?.code||"widget_protocol_violation",violation_name:e?.name||"EmbeddedCallWidgetProtocolViolationError",violation_message:e?.message||String(e),...t};this.appendLog("协议错误:当前页面收到了非法的运行态指令,已拒绝执行并保留现有通话状态。",i),typeof console<"u"&&typeof console.error=="function"&&console.error("[embedded-call-widget] protocol violation",i),await this.reportIssuedSessionEvent("protocol-violation",i),!["calling","connected","incoming"].includes(this.state)&&(this.pendingLifecycleMode=null,this.clearAutoStandbyRecovery(),this.stopSessionTouch(),this.stopPresenceTouch(),this.terminalFailureOverride=i.violation_message,this.setState("failed",i.violation_message),this.setAvailabilityState("conflicted","检测到前后端协议不一致,已停止自动恢复,请尽快排查。"))}async touchWidgetPresence(e="interval"){if(this.legacyOutboundOnly)return;this.networkOnline=typeof navigator>"u"?!0:navigator.onLine!==!1,this.pageVisible=typeof document>"u"?!0:document.visibilityState==="visible";const t=this.availabilityState==="offline";try{const i=await fetch(X(this.apiBaseUrl,"api/sip/touch-widget-presence"),{method:"POST",credentials:"include",cache:"no-store",keepalive:!0,headers:{"Content-Type":"application/json"},body:JSON.stringify((()=>{const n={presence_id:this.presenceId,state:this.state,page_url:typeof window>"u"?void 0:window.location.href,visible:this.pageVisible,network_online:this.networkOnline,client_summary:this.buildPresenceEvidenceSummary(this.state,{trigger:e})};return A(n,"site_key",this.options.siteKey),A(n,"requested_business_key",ce(this.options)),A(n,"resolved_business_key",this.issuedSession?.resolved_business_key),A(n,"display_name",this.options.displayName),A(n,"session_id",this.issuedSession?.session_id),A(n,"session_mode",this.issuedSession?.session_mode),A(n,"widget_anchor_number",this.issuedSession?.widget_anchor_number),A(n,"browser_sip_username",this.issuedSession?.browser_sip_username||this.issuedSession?.sip_username),A(n,"standby_mode",this.issuedSession?.standby_mode),A(n,"standby_state",this.issuedSession?.standby_state||this.options.standbyState),A(n,"selected_primary_account",this.options.selectedPrimaryAccount),A(n,"selected_middle_layer_account",this.options.selectedMiddleLayerAccount),A(n,"route_note",this.issuedSession?.route_note),n})())});if(!i.ok)throw new Error(`运行态心跳失败:${i.status}`);const s=await i.json().catch(()=>({}));this.presenceFailureCount=0,await this.handleServerSessionAction("touch-widget-presence",s)||this.syncAvailabilityState(),t&&await this.restartStandbyAfterConnectivity(`presence-${e}`)}catch(i){if(Oe(i)){await this.handleProtocolViolation(i),this.syncAvailabilityState();return}if(this.presenceFailureCount+=1,this.networkOnline===!1||Xe(i)||this.presenceFailureCount>=Tt){const r=this.networkOnline===!1?"当前网络连接已断开,正在等待恢复。":"当前无法连接通话服务,正在自动尝试恢复。";this.setAvailabilityState("offline",r)}else this.setAvailabilityState("recovering","正在确认后台连接状态。");this.presenceFailureCount<=Tt&&this.appendLog("widget 运行态心跳失败",{trigger:e,failure_count:this.presenceFailureCount,message:i?.message||String(i)})}}startPresenceTouch(){this.legacyOutboundOnly||(this.touchWidgetPresence("mount"),this.presenceTouchTimer||(this.presenceTouchTimer=window.setInterval(()=>{this.touchWidgetPresence("interval")},Ii)))}async touchIssuedSession(e,t=null){if(!this.issuedSession?.session_id)return;const i=this.issuedSession.session_id;try{const s=await fetch(X(this.apiBaseUrl,"api/sip/touch-call-session"),{method:"POST",credentials:"include",cache:"no-store",keepalive:!0,headers:{"Content-Type":"application/json"},body:JSON.stringify({session_id:i,state:e,client_summary:this.buildClientEvidenceSummary(e,t)})});if(!s.ok){const n=new Error(`会话心跳失败:${s.status}`);throw n.status=s.status,n}const r=await s.json().catch(()=>({}));await this.handleServerSessionAction("touch-call-session",r)}catch(s){if(Oe(s)){await this.handleProtocolViolation(s);return}if(s?.status===404&&this.wasSessionRecentlyReleased(i))return;this.appendLog("网页通话会话心跳失败",{session_id:i,state:e,message:s?.message||String(s)}),s?.status===404&&this.handleMissingIssuedSession(i,e)}}async handleMissingIssuedSession(e,t){if(!(this.sessionRecoveryInFlight||this.issuedSession?.session_id!==e)){this.sessionRecoveryInFlight=(async()=>{this.stopSessionTouch(),this.appendLog("网页电话待机会话已失效,准备自动恢复。",{session_id:e,state:t}),this.setAvailabilityState("recovering","原待机会话已失效,正在自动恢复。"),this.issuedSession?.session_id===e&&(this.issuedSession=null),!this.legacyOutboundOnly&&["standby","registering","standbyRequesting","failed","idle","missed","rejected","ended"].includes(this.state)&&(this.setState("standbyRequesting","待机会话已失效,正在自动重新进入待机。"),await this.startStandby({force:!0}))})();try{await this.sessionRecoveryInFlight}finally{this.sessionRecoveryInFlight=null}}}async reportIssuedSessionEvent(e,t=null,i=null){if(!this.issuedSession?.session_id)return;const s=this.issuedSession.session_id,r=i||this.state;let n=null,a="";try{const d=await fetch(X(this.apiBaseUrl,"api/sip/report-call-session-event"),{method:"POST",credentials:"include",cache:"no-store",keepalive:!0,headers:{"Content-Type":"application/json"},body:JSON.stringify({session_id:s,source:"widget-runtime",event:e,state:r,detail:this.buildClientEvidenceSummary(r,t)})});if(!d.ok){n=d.status;const f=await d.json().catch(()=>({}));throw a=f?.detail?String(f.detail):"",new Error(a||`事件留证失败:${d.status}`)}}catch(d){await fetch(X(this.apiBaseUrl,"api/sip/report-call-session-event-delivery-failure"),{method:"POST",credentials:"include",cache:"no-store",keepalive:!0,headers:{"Content-Type":"application/json"},body:JSON.stringify({session_id:s,source:"widget-runtime",event:e,state:r,detail:this.buildClientEvidenceSummary(r,t),delivery_error:{status:typeof n=="number"?n:null,detail:a||"",message:d?.message||String(d)}})}).catch(()=>{}),this.appendLog("网页通话事件留证失败",{session_id:s,event:e,state:r,message:d?.message||String(d)})}}stopSessionTouch(){this.sessionTouchTimer&&(window.clearInterval(this.sessionTouchTimer),this.sessionTouchTimer=null)}syncSessionTouch(e){if(!(!!this.issuedSession?.session_id&&["connected","registered","dialing","ringing","answered","standby","incoming"].includes(e))){this.stopSessionTouch();return}this.touchIssuedSession(e),this.sessionTouchTimer||(this.sessionTouchTimer=window.setInterval(()=>{this.touchIssuedSession(this.state)},xi))}setState(e,t=""){this.state=e,this.refs.status.textContent=t||te[e]||te.idle,this.syncAvailabilityState(),this.render(),this.emitHostCallback("onStateChange",this.getSnapshot())}appendLog(e,t){const i=document.createElement("div");for(i.className="log",i.textContent=Pi(e,t),this.refs.logs.prepend(i);this.refs.logs.children.length>8;)this.refs.logs.lastElementChild?.remove()}render(){const e=["requesting","standbyRequesting","registering","calling"].includes(this.state),t=["calling","connected"].includes(this.state),i=!!(this.client||this.issuedSession),s=!this.legacyOutboundOnly&&!i&&!["offline","conflicted"].includes(this.availabilityState)&&["idle","failed","ended"].includes(this.state);this.refs.status&&(this.refs.status.className=["status",this.availabilityState==="offline"?"status--offline":this.availabilityState==="recovering"?"status--recovering":this.availabilityState==="conflicted"?"status--conflicted":""].filter(Boolean).join(" ")),this.legacyOutboundOnly?(this.refs.primary.disabled=e,this.refs.primary.textContent=t?"通话进行中":"连接并呼叫",this.refs.secondary.disabled=!t&&!i,this.refs.secondary.textContent=t?"挂断并清理":"断开并清理"):(this.refs.primary.disabled=e||s||this.state==="connected",this.state==="incoming"?this.refs.primary.textContent="接听来电":this.state==="connected"?this.refs.primary.textContent="通话进行中":e||s?this.availabilityState==="working"?this.refs.primary.textContent="正在建立呼叫":this.availabilityState==="preparing"?this.refs.primary.textContent="正在准备网页电话":this.refs.primary.textContent=this.state==="calling"?"通话进行中":"正在恢复网页电话":this.availabilityState==="offline"?this.refs.primary.textContent="网络恢复后再试":this.availabilityState==="conflicted"?this.refs.primary.textContent="协议冲突待排查":!i||["idle","failed","ended"].includes(this.state)?this.refs.primary.textContent="恢复网页电话待机":this.refs.primary.textContent="呼叫管理员",this.refs.secondary.disabled=!i,this.refs.secondary.textContent=this.state==="incoming"?"拒接来电":this.state==="connected"?"挂断通话":"断开电话");const r=String(this.options.siteKey||"").trim(),n=String(this.bootstrap?.default_site_key||"").trim(),a=String(ce(this.options)||"").trim(),d=String(this.bootstrap?.default_business_key||"").trim(),f=r||(n?`${n}(服务端默认站点)`:"等待服务端解析"),h=this.issuedSession?.resolved_business_key||a||(d?`${d}(服务端默认规则)`:"等待服务端解析");this.legacyOutboundOnly?this.refs.meta.textContent=`入站规则:${h};站点键:${f}`:this.refs.meta.textContent=`站点键:${f};网页电话会先进入可被叫待机;访客主动呼叫默认规则:${h}`,this.availabilityState==="offline"?this.refs.hint.textContent=this.networkOnline===!1?"当前浏览器网络已断开。系统会在网络恢复后自动尝试重连网页电话。":"当前无法连接通话服务。系统会继续自动恢复,暂时不要重复点击。":this.availabilityState==="preparing"?this.refs.hint.textContent="当前正在准备待机能力。只要页面在线,系统会自动进入可呼入、可呼出的网页电话状态。":this.availabilityState==="working"?this.state==="incoming"?this.refs.hint.textContent="当前已有来电,直接接听或拒接即可;处理完成后会自动回到待机。":this.state==="connected"?this.refs.hint.textContent="当前通话已接通,挂断后会自动回到待机,不需要额外刷新页面。":this.refs.hint.textContent="当前正在切换到外呼链路,请等待振铃、接通或自动回到待机。":this.availabilityState==="recovering"?this.refs.hint.textContent="当前页面仍在线,系统正在自动恢复可被叫待机,不需要刷新页面或手动切换模式。":this.availabilityState==="conflicted"?this.refs.hint.textContent="检测到前后端协议不一致,当前已停止自动恢复。请先排查版本和协议口径,再继续使用。":this.refs.hint.textContent=this.isMobileViewport?Ri:"桌面网页可直接使用;若宿主站点启用了来源白名单或接入令牌,请按站点配置提供对应参数。"}async destroy(){this.clearAutoStandbyRecovery(),await this.disconnectAndCleanup("destroy-widget",{suppressStateReset:!0}),typeof document<"u"&&this.visibilityHandler&&(document.removeEventListener("visibilitychange",this.visibilityHandler),this.visibilityHandler=null),this.stopSessionTouch(),this.stopPresenceTouch(),this.stopTransportDisconnectGrace(),this.pendingLifecycleMode=null,this.pendingIncomingCall=null,typeof window<"u"&&(this.onlineHandler&&(window.removeEventListener("online",this.onlineHandler),this.onlineHandler=null),this.offlineHandler&&(window.removeEventListener("offline",this.offlineHandler),this.offlineHandler=null),this.beforeUnloadHandler&&(window.removeEventListener("beforeunload",this.beforeUnloadHandler),this.beforeUnloadHandler=null),this.pageHideHandler&&(window.removeEventListener("pagehide",this.pageHideHandler),this.pageHideHandler=null)),this.e2eBridgeEnabled&&typeof window<"u"&&window.__embeddedCallWidgetE2E__&&delete window.__embeddedCallWidgetE2E__,this.shadowRoot.innerHTML=""}}function Rt(o){return new Ui(o)}return typeof window<"u"&&(window.__EmbeddedCallWidgetRuntime__={createEmbeddedCallWidgetRuntime:Rt}),Fe.createEmbeddedCallWidgetRuntime=Rt,Object.defineProperty(Fe,Symbol.toStringTag,{value:"Module"}),Fe})({});
|
|
321
|
+
`,this.refs.trigger=this.shadowRoot.querySelector('[data-role="trigger"]'),this.refs.triggerBadge=this.shadowRoot.querySelector('[data-role="trigger-badge"]'),this.refs.panelShell=this.shadowRoot.querySelector('[data-role="panel-shell"]'),this.refs.panel=this.shadowRoot.querySelector('[data-role="panel"]'),this.refs.panelEyebrow=this.shadowRoot.querySelector('[data-role="panel-eyebrow"]'),this.refs.panelTitle=this.shadowRoot.querySelector('[data-role="panel-title"]'),this.refs.panelDetail=this.shadowRoot.querySelector('[data-role="panel-detail"]'),this.refs.actions=this.shadowRoot.querySelector('[data-role="actions"]'),this.refs.status=this.shadowRoot.querySelector('[data-role="status"]'),this.refs.debugPanel=this.shadowRoot.querySelector('[data-role="debug-panel"]'),this.refs.availability=this.shadowRoot.querySelector('[data-role="availability"]'),this.refs.hint=this.shadowRoot.querySelector('[data-role="hint"]'),this.refs.meta=this.shadowRoot.querySelector('[data-role="meta"]'),this.refs.primary=this.shadowRoot.querySelector('[data-role="primary"]'),this.refs.secondary=this.shadowRoot.querySelector('[data-role="secondary"]'),this.refs.logs=this.shadowRoot.querySelector('[data-role="logs"]'),this.refs.audio=this.shadowRoot.querySelector('[data-role="audio"]'),this.refs.trigger.addEventListener("click",()=>{this.handleTriggerClick()}),this.refs.primary.addEventListener("click",()=>{this.handlePrimaryAction()}),this.refs.secondary.addEventListener("click",()=>{this.handleSecondaryAction()}),this.bindPageLifecycle(),this.registerE2EBridge(),this.startPresenceTouch(),this.render()}bindPageLifecycle(){typeof document>"u"||(this.visibilityHandler=()=>{if(this.pageVisible=document.visibilityState==="visible",document.visibilityState==="hidden"){this.reportIssuedSessionEvent("visibility-hidden",{visible:!1}),this.touchWidgetPresence("visibility-hidden"),this.issuedSession?.session_id&&this.touchIssuedSession(this.state,{trigger:"visibility-hidden"}),this.appendLog("页面已切到后台",{state:this.state,advice:"系统会继续自动保活;回到前台后请确认页面仍保持活动。"}),this.isMobileViewport&&["requesting","registering","calling","connected"].includes(this.state)&&(this.stateDetail="页面已切到后台;手机网页回到前台后请确认通话仍在继续。",this.render());return}if(this.isMobileViewport&&(this.appendLog("页面已回到前台",{state:this.state}),["requesting","registering","calling","connected"].includes(this.state)&&(this.stateDetail=ie[this.state]||ie.idle,this.render())),this.touchWidgetPresence("visibility-visible"),!this.legacyOutboundOnly&&["standby","registering","standbyRequesting","failed","idle","missed","rejected","ended"].includes(this.state)){const e=this.client?.getConnectionSnapshot?.()||null,t=!!(e?.connected&&(this.state!=="standby"||e?.registered));this.issuedSession?.session_id&&t?this.touchIssuedSession(this.state,{trigger:"visibility-visible"}):(this.appendLog("页面回到前台后检测到待机链路未处于健康状态,准备自动重建。",{state:this.state,has_session:!!this.issuedSession?.session_id,client_snapshot:e}),this.client||this.issuedSession?.session_id?this.disconnectAndCleanup("visibility-visible-unhealthy-client"):this.startStandby({force:!0}))}this.reportIssuedSessionEvent("visibility-visible",{visible:!0}),this.render()},document.addEventListener("visibilitychange",this.visibilityHandler),typeof window<"u"&&(this.onlineHandler=()=>{this.networkOnline=!0,this.setAvailabilityState("recovering","网络已恢复,正在重新连接网页电话。"),this.touchWidgetPresence("browser-online"),this.legacyOutboundOnly||this.restartStandbyAfterConnectivity("browser-online")},this.offlineHandler=()=>{this.networkOnline=!1,this.setAvailabilityState("offline","当前网络连接已断开,正在等待恢复。"),["incoming","connected"].includes(this.state)?this.render():this.setState("failed","当前网络连接已断开,正在等待恢复。")},window.addEventListener("online",this.onlineHandler),window.addEventListener("offline",this.offlineHandler),this.beforeUnloadHandler=()=>{this.flushUnloadCleanup("beforeunload")},this.pageHideHandler=e=>{e?.persisted||this.flushUnloadCleanup("pagehide")},window.addEventListener("beforeunload",this.beforeUnloadHandler),window.addEventListener("pagehide",this.pageHideHandler)))}open(){this.mountNode.scrollIntoView({block:"nearest",inline:"nearest"})}beginLifecycleRun(){return this.lifecycleRunId+=1,this.lifecycleRunId}assertLifecycleRunCurrent(e){if(e!==this.lifecycleRunId)throw Gi("网页电话已切换到新的连接流程,旧流程不再继续。")}emitHostCallback(e,t){const i=this.options?.[e];if(Bi(i))try{i(t)}catch(s){this.appendLog("宿主回调执行失败",{callback:e,message:s?.message||String(s)})}}getSnapshot(){const e=this.getVisibleState();return{mode:this.mode,state:this.state,stateDetail:this.stateDetail,visibleState:e,panelOpen:this.isPanelVisible(),sessionMode:this.issuedSession?.session_mode||null,sessionId:this.issuedSession?.session_id||null,siteKey:this.options.siteKey||this.bootstrap?.default_site_key||null,businessKey:this.issuedSession?.resolved_business_key||le(this.options,this.bootstrap)||null,standbyMode:this.issuedSession?.standby_mode||null,standbyState:this.issuedSession?.standby_state||this.options.standbyState||null,widgetSipNumber:this.issuedSession?.widget_anchor_number||null,browserSipUsername:this.issuedSession?.browser_sip_username||this.issuedSession?.sip_username||null,routeNote:this.issuedSession?.route_note||null,incomingAnchors:Array.isArray(this.issuedSession?.incoming_anchors)?this.issuedSession.incoming_anchors:[],hasClient:!!this.client,hasIssuedSession:!!this.issuedSession?.session_id,primaryText:this.refs.primary?.textContent?.trim()||"",secondaryText:this.refs.secondary?.textContent?.trim()||"",statusText:this.refs.status?.textContent?.trim()||"",availabilityState:this.availabilityState,availabilityLabel:this.refs.availability?.textContent?.trim()||"",triggerBadge:this.refs.triggerBadge?.textContent?.trim()||"",missedIncomingCount:this.missedIncomingCount,triggerHintDismissed:this.triggerHintDismissed,debugRequested:this.debugRequested,debugPanelEnabled:this.debugPanelEnabled,presenceId:this.presenceId,networkOnline:this.networkOnline,pendingIncomingCall:this.pendingIncomingCall}}getVisibleState(){return this.transientPanelState?this.transientPanelState:this.state==="incoming"?"ringing":["requesting","registering","calling"].includes(this.state)?"dialing":this.state==="connected"?"connected":"idle"}isPanelVisible(){return this.getVisibleState()!=="idle"}clearPanelAutoClose(){this.panelAutoCloseTimer&&(window.clearTimeout(this.panelAutoCloseTimer),this.panelAutoCloseTimer=null)}clearTransientPanelState(){this.clearPanelAutoClose(),this.transientPanelState=null,this.transientPanelDetail="",this.render()}setTransientPanelState(e,t="",i=Ii){this.clearPanelAutoClose(),this.transientPanelState=e,this.transientPanelDetail=t,this.render(),i>0&&(this.panelAutoCloseTimer=window.setTimeout(()=>{this.panelAutoCloseTimer=null,this.transientPanelState=null,this.transientPanelDetail="",this.render()},i))}markDebugPanelEnabled(e){!this.debugRequested||!this.hasAccessToken||this.debugPanelEnabled||(this.debugPanelEnabled=!0,this.appendLog("调试模式门禁已成立,开始展示调试面板。",{source:e}),this.render())}dismissTriggerHint(){this.triggerHintDismissed||(this.triggerHintDismissed=!0,Fi(this.triggerHintStorageKey,!0))}clearMissedIncomingCount(){this.missedIncomingCount&&(this.missedIncomingCount=0)}incrementMissedIncomingCount(){this.missedIncomingCount+=1}async handleTriggerClick(){if(this.dismissTriggerHint(),this.clearMissedIncomingCount(),this.clearTransientPanelState(),this.open(),["requesting","registering","calling","connected","incoming"].includes(this.state)){this.render();return}await this.connectAndCall()}registerE2EBridge(){if(!this.e2eBridgeEnabled||typeof window>"u")return;const e=window.location.hostname||"example.invalid";window.__embeddedCallWidgetE2E__={getSnapshot:()=>this.getSnapshot(),simulateIncomingCall:(t={})=>{const i=t.host||e,s=t.user||"2001";return this.pendingIncomingCall={displayName:t.displayName||"测试来电",user:s,host:i,direction:"inbound",uri:t.uri||`sip:${s}@${i}`,e2eSimulated:!0},this.clearPanelAutoClose(),this.transientPanelState=null,this.transientPanelDetail="",this.setAvailabilityState("working","已有新来电,请直接接听或挂断。"),this.setState("incoming"),this.emitHostCallback("onIncomingCall",this.pendingIncomingCall),this.getSnapshot()},simulateOutboundDialing:(t={})=>(this.dismissTriggerHint(),this.clearMissedIncomingCount(),this.clearPanelAutoClose(),this.transientPanelState=null,this.transientPanelDetail="",this.pendingIncomingCall=t&&typeof t=="object"?{...t,direction:"outbound",e2eSimulated:!0}:null,this.setAvailabilityState("working","测试桥已模拟发起外呼。"),this.setState("calling",t?.message||"测试桥已模拟拨打管理员。"),this.getSnapshot()),simulateOutboundConnected:(t={})=>(this.clearPanelAutoClose(),this.transientPanelState=null,this.transientPanelDetail="",t&&typeof t=="object"&&(this.pendingIncomingCall={...this.pendingIncomingCall||{},...t,direction:"outbound",e2eSimulated:!0}),this.setAvailabilityState("working","测试桥已模拟外呼接通。"),this.setState("connected",t?.message||"测试桥已模拟通话接通。"),this.getSnapshot()),answerIncomingCall:async()=>(await this.answerIncomingCall(),this.getSnapshot()),declineIncomingCall:async()=>(await this.declineIncomingCall(),this.getSnapshot()),hangupCall:async()=>(await this.hangupCall(),this.getSnapshot()),destroyWidget:async()=>(await this.destroy(),null)}}async handlePrimaryAction(){if(this.state==="incoming"){await this.answerIncomingCall();return}["calling","connected"].includes(this.state)||await this.handleTriggerClick()}async handleSecondaryAction(){if(this.state==="incoming"){await this.declineIncomingCall();return}if(["calling","connected"].includes(this.state)&&this.client){await this.hangupCall();return}await this.disconnectAndCleanup("manual-disconnect")}async connectAndCall(){if(["requesting","registering","calling","connected"].includes(this.state))return;const e=this.beginLifecycleRun();try{this.terminalFailureOverride="",this.clearAutoStandbyRecovery(),this.pendingLifecycleMode="outbound",this.setAvailabilityState("working","正在建立呼叫链路。");const t=this.issuedSession?.session_mode==="widget_standby"&&(this.issuedSession?.browser_sip_username||this.issuedSession?.sip_username)||null;!this.legacyOutboundOnly&&this.issuedSession?.session_mode==="widget_standby"&&(this.appendLog("访客主动呼叫前,先释放当前待机会话并切换到呼叫链路。",{widget_anchor_number:this.issuedSession?.widget_anchor_number||null,resolved_business_key:this.issuedSession?.resolved_business_key||le(this.options)||null}),await this.disconnectAndCleanup("switch-to-outbound-call",{preserveLifecycleRun:!0,suppressStateReset:!0,suppressClientTeardownState:"switch-to-outbound-call"}),this.assertLifecycleRunCurrent(e)),this.setState("requesting"),await this.loadBootstrap(),this.assertLifecycleRunCurrent(e),this.turnIceServers=await this.fetchTurnIceServers(),this.assertLifecycleRunCurrent(e);const i=await this.fetchIssuedSession({preferredBrowserSipUsername:t});this.assertLifecycleRunCurrent(e),await this.ensureClient(i),this.assertLifecycleRunCurrent(e),this.setState("registering"),await this.client.ensureReady(),this.assertLifecycleRunCurrent(e),this.setState("calling"),this.syncAvailabilityState(),await this.client.call(i.target),this.assertLifecycleRunCurrent(e),this.appendLog("已发起呼叫",{target:i.target,route_note:i.routeNote||null})}catch(t){if(this.pendingLifecycleMode=null,_t(t)){this.appendLog("已忽略过期的网页电话呼叫流程",{message:t?.message||String(t)});return}if(Oe(t)){await this.handleProtocolViolation(t);return}const i=t?.message||String(t);if(this.terminalFailureOverride=i,this.setState("failed",i),this.setTransientPanelState("failed","当前暂时无法接通,请稍后再试。"),Qe(t)||this.networkOnline===!1?this.setAvailabilityState("offline",this.networkOnline===!1?"当前网络连接已断开,正在等待恢复。":"当前无法连接通话服务,正在自动尝试恢复。"):this.setAvailabilityState("recovering","呼叫失败,正在准备恢复网页电话待机。"),this.appendLog("连接并呼叫失败",{message:i}),await this.releaseIssuedSession("failed","connect-and-call-failed"),!this.legacyOutboundOnly){this.appendLog("呼叫失败后,网页电话将恢复待机。",{message:i}),await this.startStandby({force:!0});return}this.setState("failed",i)}}async startStandby(e={}){if(this.legacyOutboundOnly)throw new Error("当前 widget 仍处于 legacy outbound 兼容模式");const{force:t=!1}=e;if(!t&&["standbyRequesting","registering","incoming","connected"].includes(this.state))return;const i=this.beginLifecycleRun();try{this.clearAutoStandbyRecovery(),this.pendingLifecycleMode="standby",this.terminalFailureOverride="",this.setState("standbyRequesting"),this.setAvailabilityState("preparing","正在申请新的待机会话。"),await this.loadBootstrap(),this.assertLifecycleRunCurrent(i),this.turnIceServers=await this.fetchTurnIceServers(),this.assertLifecycleRunCurrent(i);const s=await this.fetchStandbySession();this.assertLifecycleRunCurrent(i),await this.ensureClient(s),this.assertLifecycleRunCurrent(i),this.setState("registering","待机会话已拿到,正在连接并执行 REGISTER。"),await this.client.ensureReady(),this.assertLifecycleRunCurrent(i),this.pendingLifecycleMode=null,this.setState("standby"),this.setAvailabilityState("ready","当前可被呼叫,也可由访客主动发起呼叫。"),this.appendLog("widget 已进入待机",{session_id:this.issuedSession?.session_id||null,route_business_key:this.issuedSession?.resolved_business_key||le(this.options)||null,standby_mode:this.issuedSession?.standby_mode||null,widget_anchor_number:this.issuedSession?.widget_anchor_number||null,browser_sip_username:this.issuedSession?.browser_sip_username||this.issuedSession?.sip_username||null}),this.emitHostCallback("onStandbyReady",this.getSnapshot())}catch(s){if(_t(s)){this.appendLog("已忽略过期的网页电话待机流程",{message:s?.message||String(s)});return}if(this.pendingLifecycleMode=null,Oe(s)){await this.handleProtocolViolation(s);return}const r=s?.message||String(s);this.terminalFailureOverride=r,this.setState("failed",r),Qe(s)||this.networkOnline===!1?this.setAvailabilityState("offline",this.networkOnline===!1?"当前网络连接已断开,正在等待恢复。":"当前无法连接通话服务,正在自动尝试恢复。"):this.setAvailabilityState("recovering","当前未能完成待机注册,系统会继续自动恢复。"),this.appendLog("进入待机失败",{message:r}),await this.releaseIssuedSession("failed","standby-start-failed"),this.setState("failed",r),!this.legacyOutboundOnly&&this.networkOnline!==!1&&this.scheduleAutoStandbyRecovery("standby-start-failed")}}async ensureClient(e){const t={sip_username:e.sipUsername,sip_password:e.password,sip_domain:e.sipDomain,webrtc_url:e.transport,ice_servers:this.turnIceServers};this.client?.matchesAccount(t)||(this.client&&await this.client.destroy(),this.client=new Si(t,{remoteAudioElement:this.refs.audio,onStateChange:(i,s)=>{this.handleClientState(i,s)},onError:i=>this.appendLog("SIP 客户端错误",{message:i?.message||String(i)})}))}async handleClientState(e,t={}){if(this.syncSessionTouch(e),this.reportIssuedSessionEvent(e,t,e),(e==="connected"||e==="registered"||e==="ringing"||e==="dialing"||e==="answered")&&await this.clearTransportDisconnectGrace(!0),e==="registered"){this.pendingLifecycleMode=null,this.issuedSession?.session_mode==="widget_standby"?(this.setState("standby"),this.setAvailabilityState("ready","当前可被呼叫,也可由访客主动发起呼叫。")):this.setState("registering","REGISTER 已完成,正在准备发起呼叫。");return}if(e==="incoming"){this.pendingLifecycleMode=null,this.pendingIncomingCall=t&&typeof t=="object"?{...t}:null,this.clearPanelAutoClose(),this.transientPanelState=null,this.transientPanelDetail="",this.setState("incoming"),this.setAvailabilityState("working","已有新来电,请直接接听或拒接。"),this.appendLog("收到新的来电",this.pendingIncomingCall),this.emitHostCallback("onIncomingCall",this.pendingIncomingCall);return}if(e==="ringing"||e==="dialing"){this.setState("calling",t?.message||ie.calling);return}if(e==="answered"){this.pendingLifecycleMode=null,this.terminalFailureOverride="";const i=this.pendingIncomingCall||t||null;this.clearPanelAutoClose(),this.transientPanelState=null,this.transientPanelDetail="",this.setState("connected"),this.setAvailabilityState("working","当前通话已接通。"),this.emitHostCallback("onCallAnswered",i);return}if(e==="terminated"){if(this.issuedSession?.session_mode==="widget_standby"){await this.handleStandbyTermination(t);return}t&&typeof t=="object"&&(t.source==="invite-response"||t.source==="invite-exception"||t.code||t.status||t.stage)&&(this.terminalFailureOverride=t?.message||ie.failed,this.setState("failed",this.terminalFailureOverride)),await this.finalizeAfterTermination(t?.hangupSource||"terminated");return}if(e==="failed"){if(this.isExpectedClientTeardown())return;this.pendingLifecycleMode=null,await this.clearTransportDisconnectGrace(!1),this.stopSessionTouch(),this.terminalFailureOverride=t?.message||ie.failed,this.setState("failed",this.terminalFailureOverride),this.setTransientPanelState("failed","当前暂时无法接通,请稍后再试。"),this.setAvailabilityState("recovering","通话链路异常断开,系统会继续自动恢复。"),await this.releaseIssuedSession("failed","sip-client-failed");return}if(e==="disconnected"||e==="unregistered"){if(this.isExpectedClientTeardown()||this.isExpectedTermination()||!this.issuedSession?.session_id&&this.pendingLifecycleMode==="standby")return;if(this.stopSessionTouch(),["calling","connected"].includes(this.state)){this.setState("connected","SIP 信令短暂中断,正在等待恢复。"),this.setAvailabilityState("recovering","通话信令短暂中断,正在等待恢复。"),this.scheduleTransportDisconnectGrace(e);return}const s=this.terminalFailureOverride||this.client?.lastFailureMeta?.message||null;if(s){this.terminalFailureOverride=s,this.setState("failed",s),this.setTransientPanelState("failed","当前暂时无法接通,请稍后再试。");return}if(this.state==="failed")return;this.state!=="idle"&&this.state!=="ended"&&(this.pendingLifecycleMode=null,this.setState("ended"),this.setAvailabilityState("preparing","通话已结束,正在自动返回网页电话待机。"),this.scheduleAutoStandbyRecovery(`client-${e}`))}}stopTransportDisconnectGrace(){this.transportDisconnectTimer&&(window.clearTimeout(this.transportDisconnectTimer),this.transportDisconnectTimer=null),this.transportDisconnectContext=null}sameTransportDisconnectContext(e){return!e||!this.issuedSession?.session_id?!1:e.sessionId===this.issuedSession.session_id}async clearTransportDisconnectGrace(e){const t=this.transportDisconnectContext,i=!!(e&&t?.reported&&this.sameTransportDisconnectContext(t));this.stopTransportDisconnectGrace(),i&&(await this.reportIssuedSessionEvent("transport-restored",{disconnectDurationMs:Date.now()-(t.startedAt||Date.now()),graceMs:Re},this.state),this.appendLog("网页通话信令已恢复",{disconnectDurationMs:Date.now()-(t.startedAt||Date.now()),graceMs:Re}))}scheduleTransportDisconnectGrace(e){if(!this.issuedSession?.session_id)return;this.stopTransportDisconnectGrace();const t={sessionId:this.issuedSession.session_id,startedAt:Date.now(),reported:!1,state:e};this.transportDisconnectContext=t,this.transportDisconnectTimer=window.setTimeout(()=>{this.transportDisconnectTimer=null,this.sameTransportDisconnectContext(t)&&(t.reported=!0,this.reportIssuedSessionEvent("transport-disconnected",{state:e,graceMs:Re},this.state),this.appendLog("网页通话信令断开超过宽限窗口",{graceMs:Re,state:e}))},Re)}async finalizeAfterTermination(e){if(!this.finalizing){this.beginLifecycleRun(),this.finalizing=!0;try{this.pendingLifecycleMode=null,this.stopSessionTouch(),this.stopTransportDisconnectGrace(),await this.releaseIssuedSession("released",e),this.client&&(await this.client.destroy(),this.client=null);const t=this.terminalFailureOverride||(this.state==="failed"?this.stateDetail||ie.failed:"");if(this.setTransientPanelState(t?"failed":"ended",t?"当前暂时无法接通,请稍后再试。":"本次通话已结束。"),!this.legacyOutboundOnly){t?this.setState("failed",t):this.setState("ended"),this.setAvailabilityState("preparing","页面仍在线,正在自动回到待机。"),this.appendLog("通话已结束,网页电话正在自动回到待机。",{reason:e}),await this.startStandby({force:!0});return}t?this.setState("failed",t):this.setState("ended"),this.appendLog("通话已结束并完成清理",{reason:e})}finally{this.finalizing=!1}}}async handleStandbyTermination(e={}){this.stopTransportDisconnectGrace();const t=this.state,i=e?.hangupSource||"terminated";t==="incoming"?(this.incrementMissedIncomingCount(),i==="local"?(this.setState("standby","当前来电已拒接,widget 仍保持可用。"),this.setAvailabilityState("ready","当前来电已拒接,widget 仍保持可用。"),this.emitHostCallback("onCallRejected",this.pendingIncomingCall||e||null)):(this.setState("standby","当前来电未接听,widget 仍保持可用。"),this.setAvailabilityState("ready","当前来电未接听,widget 仍保持可用。"),this.emitHostCallback("onCallMissed",this.pendingIncomingCall||e||null)),this.setTransientPanelState("ended","本次来电已结束。")):(this.setState("standby","上一通来电已结束,继续等待下一通来电。"),this.setAvailabilityState("ready","当前可被呼叫,也可由访客主动发起呼叫。"),this.setTransientPanelState("ended","本次通话已结束。")),this.appendLog("待机会话中的来电已结束",{hangupSource:i,previousState:t}),this.pendingIncomingCall=null}async answerIncomingCall(){if(this.state==="incoming"){if(this.clearPanelAutoClose(),this.transientPanelState=null,this.transientPanelDetail="",this.e2eBridgeEnabled&&this.pendingIncomingCall?.e2eSimulated){this.setState("connected","测试桥已模拟接听当前来电。"),this.emitHostCallback("onCallAnswered",this.pendingIncomingCall);return}if(!this.client&&this.e2eBridgeEnabled){this.setState("connected","测试桥已模拟接听当前来电。"),this.emitHostCallback("onCallAnswered",this.pendingIncomingCall);return}if(!this.client)throw new Error("当前没有可接听的 SIP 会话");await this.client.answer()}}async declineIncomingCall(){if(this.state==="incoming"){if(this.e2eBridgeEnabled&&this.pendingIncomingCall?.e2eSimulated){this.incrementMissedIncomingCount(),this.setState("standby","测试桥已模拟拒接当前来电,网页电话已恢复待机。"),this.setTransientPanelState("ended","本次来电已结束。"),this.setAvailabilityState("ready","当前可被呼叫,也可由访客主动发起呼叫。"),this.emitHostCallback("onCallRejected",this.pendingIncomingCall),this.pendingIncomingCall=null;return}if(!this.client&&this.e2eBridgeEnabled){this.incrementMissedIncomingCount(),this.setState("standby","测试桥已模拟拒接当前来电,网页电话已恢复待机。"),this.setTransientPanelState("ended","本次来电已结束。"),this.setAvailabilityState("ready","当前可被呼叫,也可由访客主动发起呼叫。"),this.emitHostCallback("onCallRejected",this.pendingIncomingCall),this.pendingIncomingCall=null;return}if(!this.client)throw new Error("当前没有可拒接的 SIP 会话");await this.client.decline()}}async hangupCall(){if(this.e2eBridgeEnabled&&this.pendingIncomingCall?.e2eSimulated){this.legacyOutboundOnly?(this.setState("ended"),this.setTransientPanelState("ended","本次通话已结束。")):(this.setState("standby","测试桥已模拟挂断,网页电话已恢复待机。"),this.setTransientPanelState("ended","本次通话已结束。")),this.pendingIncomingCall=null;return}if(!this.client&&this.e2eBridgeEnabled){this.legacyOutboundOnly?(this.setState("ended"),this.setTransientPanelState("ended","本次通话已结束。")):(this.setState("standby","测试桥已模拟挂断,网页电话已恢复待机。"),this.setTransientPanelState("ended","本次通话已结束。")),this.pendingIncomingCall=null;return}this.client&&(this.expectTermination("hangup-call"),this.suppressExpectedClientTeardown("hangup-call"),await this.client.hangup())}async disconnectAndCleanup(e,t={}){const{preserveLifecycleRun:i=!1,suppressStateReset:s=!1,suppressClientTeardownState:r=null}=t;i||this.beginLifecycleRun(),r&&this.suppressExpectedClientTeardown(r),this.stopSessionTouch(),this.stopTransportDisconnectGrace(),this.reportIssuedSessionEvent("manual-disconnect",{reason:e},this.state),this.pendingIncomingCall=null,this.terminalFailureOverride="",this.client&&(await this.client.destroy(),this.client=null),await this.releaseIssuedSession("released",e),s||(this.pendingLifecycleMode=null,this.setState("idle"),this.setAvailabilityState("preparing","网页电话已断开,系统正在自动返回待机。"),this.appendLog("连接已断开",{reason:e}),!this.legacyOutboundOnly&&this.networkOnline!==!1&&this.scheduleAutoStandbyRecovery(e))}async loadBootstrap(){if(this.bootstrap)return this.bootstrap;const e=await fetch(X(this.apiBaseUrl,"api/sip/embedded-call-demo-bootstrap"),{credentials:"include",cache:"no-store"});if(!e.ok)throw new Error(`默认模式读取失败:${e.status}`);return this.bootstrap=await e.json(),this.bootstrap}async fetchTurnIceServers(){const e=await fetch(X(this.apiBaseUrl,"api/sip/webrtc-turn-credentials"),{credentials:"include",cache:"no-store"});if(!e.ok)return this.appendLog("TURN 凭证获取失败,继续尝试直连",{status:e.status}),[];const t=await e.json();return Array.isArray(t?.ice_servers)?t.ice_servers:[]}async fetchIssuedSession(e={}){const{preferredBrowserSipUsername:t=null}=e,i=le(this.options),s={page_url:window.location.href};A(s,"site_key",this.options.siteKey),A(s,"standby_state",this.options.standbyState),A(s,"selected_primary_account",this.options.selectedPrimaryAccount),A(s,"selected_middle_layer_account",this.options.selectedMiddleLayerAccount),A(s,"preferred_browser_sip_username",t),A(s,"display_name",this.options.displayName),A(s,"access_token",this.options.accessToken),i&&(s.business_key=i);const r=await fetch(X(this.apiBaseUrl,"api/sip/issue-call-session"),{method:"POST",credentials:"include",cache:"no-store",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!r.ok){const d=await r.json().catch(()=>({}));throw new Error(d?.detail||`会话签发失败:${r.status}`)}const n=await r.json(),o=xt(n,Ie.outbound,"issue-call-session");return this.markDebugPanelEnabled("issue-call-session"),this.issuedSession=n,this.reportIssuedSessionEvent("issued-session-fetched",{sessionId:n.session_id,targetExtension:n.target_extension,dialTargetExtension:n.dial_target_extension||n.target_extension,resolvedTargetInternalNumbers:n.resolved_target_internal_numbers||[],resolvedBusinessKey:n.resolved_business_key||null},"requesting"),this.appendLog("已获取服务端签发会话",{session_id:n.session_id,target_extension:n.target_extension,dial_target_extension:n.dial_target_extension||n.target_extension||null,resolved_target_internal_numbers:n.resolved_target_internal_numbers||[],resolved_business_key:n.resolved_business_key||null,resolved_route_mode:n.resolved_route_mode||null,route_note:n.route_note||null}),{sessionMode:o,sipUsername:n.sip_username,sipDomain:n.sip_domain,password:n.sip_password,transport:Tt({apiBaseUrl:this.apiBaseUrl,transportBaseUrl:this.options.transportBaseUrl||"",transportUrl:n.ws_server}),target:n.dial_target_extension||n.target_extension,routeNote:n.route_note||""}}async fetchStandbySession(){const e=le(this.options)||null,t={page_url:window.location.href};A(t,"site_key",this.options.siteKey),A(t,"standby_state",this.options.standbyState),A(t,"selected_primary_account",this.options.selectedPrimaryAccount),A(t,"selected_middle_layer_account",this.options.selectedMiddleLayerAccount),A(t,"display_name",this.options.displayName),A(t,"access_token",this.options.accessToken),e&&(t.business_key=e);const i=await fetch(X(this.apiBaseUrl,"api/sip/issue-widget-standby-session"),{method:"POST",credentials:"include",cache:"no-store",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!i.ok){const n=await i.json().catch(()=>({}));throw new Error(n?.detail||`待机会话签发失败:${i.status}`)}const s=await i.json(),r=xt(s,Ie.standby,"issue-widget-standby-session");return this.markDebugPanelEnabled("issue-widget-standby-session"),this.issuedSession=s,this.reportIssuedSessionEvent("standby-session-fetched",{sessionId:s.session_id,resolvedBusinessKey:s.resolved_business_key||null,standbyMode:s.standby_mode||null},"standbyRequesting"),this.appendLog("已获取 widget 待机会话",{session_id:s.session_id,resolved_business_key:s.resolved_business_key||null,standby_mode:s.standby_mode||null,standby_state:s.standby_state||null,widget_anchor_number:s.widget_anchor_number||null,browser_sip_username:s.browser_sip_username||s.sip_username||null,route_note:s.route_note||null}),{sessionMode:r,sipUsername:s.sip_username,sipDomain:s.sip_domain,password:s.sip_password,transport:Tt({apiBaseUrl:this.apiBaseUrl,transportBaseUrl:this.options.transportBaseUrl||"",transportUrl:s.ws_server}),target:null,routeNote:s.route_note||""}}async releaseIssuedSession(e,t){if(!this.issuedSession?.session_id)return;const i=this.issuedSession.session_id;this.markRecentlyReleasedSession(i,t),this.issuedSession=null,await fetch(X(this.apiBaseUrl,"api/sip/release-call-session"),{method:"POST",credentials:"include",cache:"no-store",headers:{"Content-Type":"application/json"},body:JSON.stringify({session_id:i,status:e,reason:t,client_summary:this.buildClientEvidenceSummary(e,{releaseReason:t})})}).catch(()=>{})}postLifecycleBeacon(e,t){const i=JSON.stringify(t),s=X(this.apiBaseUrl,e);if(typeof navigator<"u"&&typeof navigator.sendBeacon=="function")try{const r=new Blob([i],{type:"application/json"});if(navigator.sendBeacon(s,r))return!0}catch{}return fetch(s,{method:"POST",credentials:"include",cache:"no-store",keepalive:!0,headers:{"Content-Type":"application/json"},body:i}).catch(()=>{}),!0}flushUnloadCleanup(e){if(this.unloadCleanupStarted||(this.unloadCleanupStarted=!0,this.stopSessionTouch(),this.stopPresenceTouch(),this.stopTransportDisconnectGrace(),!this.issuedSession?.session_id))return;const t=this.issuedSession.session_id;this.markRecentlyReleasedSession(t,e),this.postLifecycleBeacon("api/sip/release-call-session",{session_id:t,status:"released",reason:e,client_summary:this.buildClientEvidenceSummary("released",{releaseReason:e})}),this.issuedSession=null}buildClientEvidenceSummary(e=null,t=null){const i={runtimeMode:"embedded-widget-runtime",widgetVersion:"2026-03-29-runtime-evidence",widgetMode:this.mode,sessionMode:this.issuedSession?.session_mode||null,state:e||this.state,visible:typeof document>"u"?!0:document.visibilityState==="visible",pageUrl:typeof window>"u"?null:window.location.href,connectionSnapshot:this.client?.getConnectionSnapshot?.()||null};return t&&typeof t=="object"&&(i.eventDetail=t),i}buildPresenceEvidenceSummary(e=null,t=null){return{...this.buildClientEvidenceSummary(e,t),presenceId:this.presenceId,availabilityState:this.availabilityState,availabilityDetail:this.availabilityDetail,networkOnline:this.networkOnline,pageVisible:this.pageVisible}}setAvailabilityState(e,t=""){this.availabilityState=e,this.availabilityDetail=t||this.availabilityDetail,this.refs.availability&&(this.refs.availability.textContent=t?`${de[e]||de.recovering} · ${t}`:de[e]||de.recovering,this.refs.availability.className=`availability availability--${e}`),this.render()}suppressExpectedClientTeardown(e,t=ki){this.expectedClientTeardown={reason:e,expiresAt:Date.now()+t}}expectTermination(e,t=1e4){this.expectedTermination={reason:e,expiresAt:Date.now()+t}}clearExpectedTermination(){this.expectedTermination=null}isExpectedTermination(){const e=this.expectedTermination;return e?e.expiresAt<=Date.now()?(this.expectedTermination=null,!1):!0:!1}isExpectedClientTeardown(){const e=this.expectedClientTeardown;return e?e.expiresAt<=Date.now()?(this.expectedClientTeardown=null,!1):!0:!1}clearAutoStandbyRecovery(){this.autoStandbyRecoveryTimer&&(window.clearTimeout(this.autoStandbyRecoveryTimer),this.autoStandbyRecoveryTimer=null)}scheduleAutoStandbyRecovery(e,t=Di){this.legacyOutboundOnly||this.networkOnline===!1||this.autoStandbyRecoveryTimer||this.client||this.issuedSession?.session_id||this.finalizing||this.pendingLifecycleMode==="outbound"||this.sessionRecoveryInFlight||this.connectivityRecoveryInFlight||["requesting","standbyRequesting","registering","calling","incoming","connected"].includes(this.state)||(this.autoStandbyRecoveryTimer=window.setTimeout(()=>{this.autoStandbyRecoveryTimer=null,!(this.legacyOutboundOnly||this.networkOnline===!1)&&(this.client||this.issuedSession?.session_id||this.finalizing||this.pendingLifecycleMode==="outbound"||(this.appendLog("检测到页面当前不在通话中,开始自动进入待机。",{reason:e}),this.startStandby({force:!0})))},t))}pruneRecentlyReleasedSessions(){const e=Date.now();for(const[t,i]of this.recentlyReleasedSessions.entries())(i?.expiresAt||0)<=e&&this.recentlyReleasedSessions.delete(t)}markRecentlyReleasedSession(e,t){e&&(this.pruneRecentlyReleasedSessions(),this.recentlyReleasedSessions.set(e,{reason:t,expiresAt:Date.now()+Pi}))}wasSessionRecentlyReleased(e){return e?(this.pruneRecentlyReleasedSessions(),this.recentlyReleasedSessions.has(e)):!1}syncAvailabilityState(){if(this.networkOnline===!1){this.setAvailabilityState("offline","当前网络连接已断开,正在等待恢复。");return}if(this.state==="incoming"){this.setAvailabilityState("working","已有新来电,请直接接听或拒接。");return}if(this.state==="connected"){this.setAvailabilityState("working","当前通话已接通。");return}if(this.state==="calling"){this.setAvailabilityState("working","正在等待对端振铃或接听。");return}if(this.pendingLifecycleMode==="outbound"&&["requesting","registering"].includes(this.state)){this.setAvailabilityState("working","正在建立呼叫链路。");return}if(["requesting","standbyRequesting","registering"].includes(this.state)){this.setAvailabilityState("preparing","页面仍在线,正在建立网页电话连接。");return}if(!this.legacyOutboundOnly&&!this.issuedSession?.session_id&&!this.pendingLifecycleMode&&["idle","ended","missed","rejected"].includes(this.state)){this.setAvailabilityState("preparing","页面仍在线,正在自动进入网页电话待机。"),this.scheduleAutoStandbyRecovery("missing-issued-session");return}if(!this.legacyOutboundOnly&&!this.issuedSession?.session_id&&!this.pendingLifecycleMode&&!["calling","connected","incoming"].includes(this.state)){this.setAvailabilityState("preparing","页面仍在线,正在重新建立网页电话待机。"),this.scheduleAutoStandbyRecovery("missing-issued-session");return}this.setAvailabilityState("ready","当前可被呼叫,也可由访客主动发起呼叫。")}stopPresenceTouch(){this.presenceTouchTimer&&(window.clearInterval(this.presenceTouchTimer),this.presenceTouchTimer=null)}async restartStandbyAfterConnectivity(e){if(!(this.legacyOutboundOnly||this.connectivityRecoveryInFlight)&&!["connected","incoming","calling","requesting","standbyRequesting","registering"].includes(this.state)){this.connectivityRecoveryInFlight=(async()=>{this.appendLog("检测到连通性已恢复,准备重建网页电话待机。",{trigger:e,state:this.state,hasSession:!!this.issuedSession?.session_id}),(this.client||this.issuedSession?.session_id)&&await this.disconnectAndCleanup(`connectivity-restored-${e}`),await this.startStandby({force:!0})})();try{await this.connectivityRecoveryInFlight}finally{this.connectivityRecoveryInFlight=null}}}async handleServerSessionAction(e,t={}){if(this.legacyOutboundOnly)return!1;const i=Ui(e,t);if(i.action!==Xe.restartStandby)return!1;const s=se(this.issuedSession?.session_mode),r=se(this.pendingLifecycleMode),n=s===Ie.outbound||r===Et.outbound,o=s===Ie.standby||r===Et.standby;if(n||!o)throw L("非待机协议上下文收到了非法的 restart_standby 指令。",{source:e,state:this.state,local_session_mode:s||null,local_lifecycle_mode:r||null,session_action:i.action,session_action_reason:i.reason,session_action_detail:i.detail,resolved_session_id:i.resolvedSessionId,resolved_widget_anchor_number:i.resolvedWidgetAnchorNumber,resolved_browser_sip_username:i.resolvedBrowserSipUsername});if(this.sessionRecoveryInFlight||this.connectivityRecoveryInFlight)return!1;this.sessionRecoveryInFlight=(async()=>{this.appendLog("服务端要求当前页面立即放弃旧锚点并重建待机。",{source:e,state:this.state,local_session_mode:s||null,local_lifecycle_mode:r||null,session_action_reason:i.reason,session_action_detail:i.detail,resolved_session_id:i.resolvedSessionId,resolved_widget_anchor_number:i.resolvedWidgetAnchorNumber,resolved_browser_sip_username:i.resolvedBrowserSipUsername}),this.setAvailabilityState("recovering",i.detail||"当前锚点已失效,正在自动切换到新的待机线路。"),(this.client||this.issuedSession?.session_id)&&await this.disconnectAndCleanup(`server-session-action-${i.reason||e}`,{preserveLifecycleRun:!0,suppressStateReset:!0}),await this.startStandby({force:!0})})();try{await this.sessionRecoveryInFlight}finally{this.sessionRecoveryInFlight=null}return!0}async handleProtocolViolation(e){const t=e?.detail&&typeof e.detail=="object"?e.detail:{},i={violation_code:e?.code||"widget_protocol_violation",violation_name:e?.name||"EmbeddedCallWidgetProtocolViolationError",violation_message:e?.message||String(e),...t};this.appendLog("协议错误:当前页面收到了非法的运行态指令,已拒绝执行并保留现有通话状态。",i),typeof console<"u"&&typeof console.error=="function"&&console.error("[embedded-call-widget] protocol violation",i),await this.reportIssuedSessionEvent("protocol-violation",i),!["calling","connected","incoming"].includes(this.state)&&(this.pendingLifecycleMode=null,this.clearAutoStandbyRecovery(),this.stopSessionTouch(),this.stopPresenceTouch(),this.terminalFailureOverride=i.violation_message,this.setState("failed",i.violation_message),this.setAvailabilityState("conflicted","检测到前后端协议不一致,已停止自动恢复,请尽快排查。"))}async touchWidgetPresence(e="interval"){if(this.legacyOutboundOnly)return;this.networkOnline=typeof navigator>"u"?!0:navigator.onLine!==!1,this.pageVisible=typeof document>"u"?!0:document.visibilityState==="visible";const t=this.availabilityState==="offline";try{const i=await fetch(X(this.apiBaseUrl,"api/sip/touch-widget-presence"),{method:"POST",credentials:"include",cache:"no-store",keepalive:!0,headers:{"Content-Type":"application/json"},body:JSON.stringify((()=>{const n={presence_id:this.presenceId,state:this.state,page_url:typeof window>"u"?void 0:window.location.href,visible:this.pageVisible,network_online:this.networkOnline,client_summary:this.buildPresenceEvidenceSummary(this.state,{trigger:e})};return A(n,"site_key",this.options.siteKey),A(n,"requested_business_key",le(this.options)),A(n,"resolved_business_key",this.issuedSession?.resolved_business_key),A(n,"display_name",this.options.displayName),A(n,"session_id",this.issuedSession?.session_id),A(n,"session_mode",this.issuedSession?.session_mode),A(n,"widget_anchor_number",this.issuedSession?.widget_anchor_number),A(n,"browser_sip_username",this.issuedSession?.browser_sip_username||this.issuedSession?.sip_username),A(n,"standby_mode",this.issuedSession?.standby_mode),A(n,"standby_state",this.issuedSession?.standby_state||this.options.standbyState),A(n,"selected_primary_account",this.options.selectedPrimaryAccount),A(n,"selected_middle_layer_account",this.options.selectedMiddleLayerAccount),A(n,"route_note",this.issuedSession?.route_note),n})())});if(!i.ok)throw new Error(`运行态心跳失败:${i.status}`);const s=await i.json().catch(()=>({}));this.presenceFailureCount=0,await this.handleServerSessionAction("touch-widget-presence",s)||this.syncAvailabilityState(),t&&await this.restartStandbyAfterConnectivity(`presence-${e}`)}catch(i){if(Oe(i)){await this.handleProtocolViolation(i),this.syncAvailabilityState();return}if(this.presenceFailureCount+=1,this.networkOnline===!1||Qe(i)||this.presenceFailureCount>=Ct){const r=this.networkOnline===!1?"当前网络连接已断开,正在等待恢复。":"当前无法连接通话服务,正在自动尝试恢复。";this.setAvailabilityState("offline",r)}else this.setAvailabilityState("recovering","正在确认后台连接状态。");this.presenceFailureCount<=Ct&&this.appendLog("widget 运行态心跳失败",{trigger:e,failure_count:this.presenceFailureCount,message:i?.message||String(i)})}}startPresenceTouch(){this.legacyOutboundOnly||(this.touchWidgetPresence("mount"),this.presenceTouchTimer||(this.presenceTouchTimer=window.setInterval(()=>{this.touchWidgetPresence("interval")},$i)))}async touchIssuedSession(e,t=null){if(!this.issuedSession?.session_id)return;const i=this.issuedSession.session_id;try{const s=await fetch(X(this.apiBaseUrl,"api/sip/touch-call-session"),{method:"POST",credentials:"include",cache:"no-store",keepalive:!0,headers:{"Content-Type":"application/json"},body:JSON.stringify({session_id:i,state:e,client_summary:this.buildClientEvidenceSummary(e,t)})});if(!s.ok){const n=new Error(`会话心跳失败:${s.status}`);throw n.status=s.status,n}const r=await s.json().catch(()=>({}));await this.handleServerSessionAction("touch-call-session",r)}catch(s){if(Oe(s)){await this.handleProtocolViolation(s);return}if(s?.status===404&&this.wasSessionRecentlyReleased(i))return;this.appendLog("网页通话会话心跳失败",{session_id:i,state:e,message:s?.message||String(s)}),s?.status===404&&this.handleMissingIssuedSession(i,e)}}async handleMissingIssuedSession(e,t){if(!(this.sessionRecoveryInFlight||this.issuedSession?.session_id!==e)){this.sessionRecoveryInFlight=(async()=>{this.stopSessionTouch(),this.appendLog("网页电话待机会话已失效,准备自动恢复。",{session_id:e,state:t}),this.setAvailabilityState("recovering","原待机会话已失效,正在自动恢复。"),this.issuedSession?.session_id===e&&(this.issuedSession=null),!this.legacyOutboundOnly&&["standby","registering","standbyRequesting","failed","idle","missed","rejected","ended"].includes(this.state)&&(this.setState("standbyRequesting","待机会话已失效,正在自动重新进入待机。"),await this.startStandby({force:!0}))})();try{await this.sessionRecoveryInFlight}finally{this.sessionRecoveryInFlight=null}}}async reportIssuedSessionEvent(e,t=null,i=null){if(!this.issuedSession?.session_id)return;const s=this.issuedSession.session_id,r=i||this.state;let n=null,o="";try{const d=await fetch(X(this.apiBaseUrl,"api/sip/report-call-session-event"),{method:"POST",credentials:"include",cache:"no-store",keepalive:!0,headers:{"Content-Type":"application/json"},body:JSON.stringify({session_id:s,source:"widget-runtime",event:e,state:r,detail:this.buildClientEvidenceSummary(r,t)})});if(!d.ok){n=d.status;const u=await d.json().catch(()=>({}));throw o=u?.detail?String(u.detail):"",new Error(o||`事件留证失败:${d.status}`)}}catch(d){await fetch(X(this.apiBaseUrl,"api/sip/report-call-session-event-delivery-failure"),{method:"POST",credentials:"include",cache:"no-store",keepalive:!0,headers:{"Content-Type":"application/json"},body:JSON.stringify({session_id:s,source:"widget-runtime",event:e,state:r,detail:this.buildClientEvidenceSummary(r,t),delivery_error:{status:typeof n=="number"?n:null,detail:o||"",message:d?.message||String(d)}})}).catch(()=>{}),this.appendLog("网页通话事件留证失败",{session_id:s,event:e,state:r,message:d?.message||String(d)})}}stopSessionTouch(){this.sessionTouchTimer&&(window.clearInterval(this.sessionTouchTimer),this.sessionTouchTimer=null)}syncSessionTouch(e){if(!(!!this.issuedSession?.session_id&&["connected","registered","dialing","ringing","answered","standby","incoming"].includes(e))){this.stopSessionTouch();return}this.touchIssuedSession(e),this.sessionTouchTimer||(this.sessionTouchTimer=window.setInterval(()=>{this.touchIssuedSession(this.state)},Ai))}setState(e,t=""){this.state=e,this.stateDetail=t||ie[e]||ie.idle,this.syncAvailabilityState(),this.render(),this.emitHostCallback("onStateChange",this.getSnapshot())}appendLog(e,t){if(!this.refs.logs)return;const i=document.createElement("div");for(i.className="log",i.textContent=qi(e,t),this.refs.logs.prepend(i);this.refs.logs.children.length>8;)this.refs.logs.lastElementChild?.remove()}render(){const e=this.getVisibleState(),t=e!=="idle",i=this.pendingIncomingCall?.displayName||this.pendingIncomingCall?.user||"管理员",s=["requesting","registering","calling","connected","incoming"].includes(this.state);let r="网页通话",n=this.options.text||"联系管理员",o=this.transientPanelDetail||"",d=null,u=null;e==="ringing"?(r="网页来电",n=i,o=o||"对方正在呼叫你,请选择接听或挂断。",d={text:"接听",className:"btn btn-primary",disabled:!1},u={text:"挂断",className:"btn btn-danger",disabled:!1}):e==="dialing"?(r="正在呼叫",o=o||"正在为你接通管理员,请稍候。",u={text:"挂断",className:"btn btn-danger",disabled:!1}):e==="connected"?(r="通话进行中",n=this.pendingIncomingCall?.displayName||n,o=o||"通话已接通,如需结束请点击挂断。",u={text:"挂断",className:"btn btn-danger",disabled:!1}):e==="ended"?(r="通话已结束",o=o||"本次通话已结束。"):e==="failed"&&(r="暂未接通",o=o||"当前暂时无法接通,请稍后再试。");const h=this.missedIncomingCount>0?String(this.missedIncomingCount):this.triggerHintDismissed?"":" ";this.refs.trigger.disabled=s,this.refs.triggerBadge.hidden=!h,this.refs.triggerBadge.textContent=h,this.refs.triggerBadge.className=this.missedIncomingCount>0?"trigger-badge":"trigger-badge trigger-badge--dot",this.refs.panelShell.className=t?"panel-shell panel-shell--visible":"panel-shell",this.refs.panel.setAttribute("aria-hidden",t?"false":"true"),this.refs.panelEyebrow.textContent=r,this.refs.panelTitle.textContent=n,this.refs.status.textContent=Ze[e]||Ze.idle,this.refs.status.className=e==="failed"?"status status--failed":"status",this.refs.panelDetail.textContent=o,this.refs.primary.hidden=!d,d?(this.refs.primary.textContent=d.text,this.refs.primary.className=d.className,this.refs.primary.disabled=d.disabled):this.refs.primary.textContent="",this.refs.secondary.hidden=!u,u?(this.refs.secondary.textContent=u.text,this.refs.secondary.className=u.className,this.refs.secondary.disabled=u.disabled):this.refs.secondary.textContent="";const m=+!!d+ +!!u;this.refs.actions.className=m<=1?"actions actions--single":"actions";const S=String(this.options.siteKey||"").trim(),x=String(this.bootstrap?.default_site_key||"").trim(),_=String(le(this.options)||"").trim(),C=String(this.bootstrap?.default_business_key||"").trim(),Q=S||(x?`${x}(服务端默认站点)`:"等待服务端解析"),p=this.issuedSession?.resolved_business_key||_||(C?`${C}(服务端默认规则)`:"等待服务端解析");this.legacyOutboundOnly?this.refs.meta.textContent=`入站规则:${p};站点键:${Q}`:this.refs.meta.textContent=`站点键:${Q};网页电话会先进入可被叫待机;访客主动呼叫默认规则:${p}`,this.refs.availability.textContent=this.availabilityDetail?`${de[this.availabilityState]||de.recovering} · ${this.availabilityDetail}`:de[this.availabilityState]||de.recovering,this.refs.availability.className=`availability availability--${this.availabilityState}`,this.availabilityState==="offline"?this.refs.hint.textContent=this.networkOnline===!1?"当前浏览器网络已断开。系统会在网络恢复后自动尝试重连网页电话。":"当前无法连接通话服务。系统会继续自动恢复,暂时不要重复点击。":this.availabilityState==="preparing"?this.refs.hint.textContent="当前正在准备待机能力。只要页面在线,系统会自动进入可呼入、可呼出的网页电话状态。":this.availabilityState==="working"?this.state==="incoming"?this.refs.hint.textContent="当前已有来电,直接接听或拒接即可;处理完成后会自动回到待机。":this.state==="connected"?this.refs.hint.textContent="当前通话已接通,挂断后会自动回到待机,不需要额外刷新页面。":this.refs.hint.textContent="当前正在切换到外呼链路,请等待振铃、接通或自动回到待机。":this.availabilityState==="recovering"?this.refs.hint.textContent="当前页面仍在线,系统正在自动恢复可被叫待机,不需要刷新页面或手动切换模式。":this.availabilityState==="conflicted"?this.refs.hint.textContent="检测到前后端协议不一致,当前已停止自动恢复。请先排查版本和协议口径,再继续使用。":this.refs.hint.textContent=this.isMobileViewport?Ri:"桌面网页可直接使用;若宿主站点启用了来源白名单或接入令牌,请按站点配置提供对应参数。",this.refs.debugPanel.hidden=!this.debugPanelEnabled}async destroy(){this.clearAutoStandbyRecovery(),this.clearPanelAutoClose(),await this.disconnectAndCleanup("destroy-widget",{suppressStateReset:!0}),typeof document<"u"&&this.visibilityHandler&&(document.removeEventListener("visibilitychange",this.visibilityHandler),this.visibilityHandler=null),this.stopSessionTouch(),this.stopPresenceTouch(),this.stopTransportDisconnectGrace(),this.pendingLifecycleMode=null,this.pendingIncomingCall=null,typeof window<"u"&&(this.onlineHandler&&(window.removeEventListener("online",this.onlineHandler),this.onlineHandler=null),this.offlineHandler&&(window.removeEventListener("offline",this.offlineHandler),this.offlineHandler=null),this.beforeUnloadHandler&&(window.removeEventListener("beforeunload",this.beforeUnloadHandler),this.beforeUnloadHandler=null),this.pageHideHandler&&(window.removeEventListener("pagehide",this.pageHideHandler),this.pageHideHandler=null)),this.e2eBridgeEnabled&&typeof window<"u"&&window.__embeddedCallWidgetE2E__&&delete window.__embeddedCallWidgetE2E__,this.shadowRoot.innerHTML=""}}function Rt(a){return new Wi(a)}return typeof window<"u"&&(window.__EmbeddedCallWidgetRuntime__={createEmbeddedCallWidgetRuntime:Rt}),Fe.createEmbeddedCallWidgetRuntime=Rt,Object.defineProperty(Fe,Symbol.toStringTag,{value:"Module"}),Fe})({});
|