mitmi 1.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/dist/Conference.d.ts +15 -0
- package/dist/HelloWorld.d.ts +3 -0
- package/dist/Stream.d.ts +19 -0
- package/dist/constants.d.ts +7 -0
- package/dist/core/SocketInteraction.d.ts +20 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -0
- package/dist/utils.d.ts +9 -0
- package/package.json +22 -0
- package/src/Conference.ts +60 -0
- package/src/HelloWorld.ts +5 -0
- package/src/Stream.ts +49 -0
- package/src/constants.ts +14 -0
- package/src/core/SocketInteraction.ts +201 -0
- package/src/index.ts +3 -0
- package/src/utils.ts +37 -0
- package/tsconfig.json +11 -0
- package/webpack.config.cjs +28 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Stream } from "./Stream";
|
|
2
|
+
declare class Conference extends EventTarget {
|
|
3
|
+
name: string;
|
|
4
|
+
id: number;
|
|
5
|
+
knownStreams: Array<Stream | void>;
|
|
6
|
+
constructor(name: string);
|
|
7
|
+
private setupListener;
|
|
8
|
+
publish(stream: Stream): void;
|
|
9
|
+
join(): void;
|
|
10
|
+
leave(): void;
|
|
11
|
+
getMembers(): void;
|
|
12
|
+
private newStream;
|
|
13
|
+
private peopleLeave;
|
|
14
|
+
}
|
|
15
|
+
export { Conference };
|
package/dist/Stream.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
declare class Stream {
|
|
2
|
+
mediastream: MediaStream;
|
|
3
|
+
domElement: undefined | HTMLVideoElement;
|
|
4
|
+
owner: string;
|
|
5
|
+
id: String;
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @param mediastream
|
|
9
|
+
* @param owner "" => ourself, id instead
|
|
10
|
+
*/
|
|
11
|
+
constructor(mediastream: MediaStream, owner: string);
|
|
12
|
+
static getCamera(video: boolean, audio: boolean): Promise<Stream>;
|
|
13
|
+
static getScreen(): void;
|
|
14
|
+
attachToElement(domElement: HTMLVideoElement): void;
|
|
15
|
+
detachToElement(): void;
|
|
16
|
+
muteAudio(): void;
|
|
17
|
+
unmuteAudio(): void;
|
|
18
|
+
}
|
|
19
|
+
export { Stream };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Stream } from "../Stream";
|
|
2
|
+
export declare class SocketInteraction extends EventTarget {
|
|
3
|
+
private socket;
|
|
4
|
+
private _userId?;
|
|
5
|
+
private _confId?;
|
|
6
|
+
private publishStream?;
|
|
7
|
+
private peerConnections;
|
|
8
|
+
init(): Promise<void>;
|
|
9
|
+
get userId(): string;
|
|
10
|
+
publish(stream: Stream): void;
|
|
11
|
+
register(confId: number): void;
|
|
12
|
+
unregister(): void;
|
|
13
|
+
private setupSocketListeners;
|
|
14
|
+
private createPeerConnection;
|
|
15
|
+
private handleOffer;
|
|
16
|
+
private handleAnswer;
|
|
17
|
+
private handleIce;
|
|
18
|
+
private removePeer;
|
|
19
|
+
private sendMessage;
|
|
20
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var t={d:(e,s)=>{for(var n in s)t.o(s,n)&&!t.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:s[n]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{Decoder:()=>gt,Encoder:()=>ft,PacketType:()=>lt,protocol:()=>dt});class s{printHello(){console.log("Hello from my-ts-package!")}}class n{constructor(t,e){this.mediastream=t,this.owner=e,this.id=e+"_usermedia"}static getCamera(t,e){return s=this,i=void 0,o=function*(){let s=yield navigator.mediaDevices.getUserMedia({video:t,audio:e});return new n(s,"")},new((r=void 0)||(r=Promise))(function(t,e){function n(t){try{c(o.next(t))}catch(t){e(t)}}function a(t){try{c(o.throw(t))}catch(t){e(t)}}function c(e){e.done?t(e.value):function(t){return t instanceof r?t:new r(function(e){e(t)})}(e.value).then(n,a)}c((o=o.apply(s,i||[])).next())});var s,i,r,o}static getScreen(){}attachToElement(t){this.domElement=t,t.srcObject=this.mediastream}detachToElement(){this.domElement&&(this.domElement.srcObject=null)}muteAudio(){this.mediastream.getAudioTracks()[0].enabled=!1}unmuteAudio(){this.mediastream.getAudioTracks()[0].enabled=!0}}const i=Object.create(null);i.open="0",i.close="1",i.ping="2",i.pong="3",i.message="4",i.upgrade="5",i.noop="6";const r=Object.create(null);Object.keys(i).forEach(t=>{r[i[t]]=t});const o={type:"error",data:"parser error"},a="function"==typeof Blob||"undefined"!=typeof Blob&&"[object BlobConstructor]"===Object.prototype.toString.call(Blob),c="function"==typeof ArrayBuffer,h=t=>"function"==typeof ArrayBuffer.isView?ArrayBuffer.isView(t):t&&t.buffer instanceof ArrayBuffer,u=({type:t,data:e},s,n)=>a&&e instanceof Blob?s?n(e):p(e,n):c&&(e instanceof ArrayBuffer||h(e))?s?n(e):p(new Blob([e]),n):n(i[t]+(e||"")),p=(t,e)=>{const s=new FileReader;return s.onload=function(){const t=s.result.split(",")[1];e("b"+(t||""))},s.readAsDataURL(t)};function d(t){return t instanceof Uint8Array?t:t instanceof ArrayBuffer?new Uint8Array(t):new Uint8Array(t.buffer,t.byteOffset,t.byteLength)}let l;const f="undefined"==typeof Uint8Array?[]:new Uint8Array(256);for(let t=0;t<64;t++)f["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charCodeAt(t)]=t;const y="function"==typeof ArrayBuffer,g=(t,e)=>{if("string"!=typeof t)return{type:"message",data:_(t,e)};const s=t.charAt(0);return"b"===s?{type:"message",data:m(t.substring(1),e)}:r[s]?t.length>1?{type:r[s],data:t.substring(1)}:{type:r[s]}:o},m=(t,e)=>{if(y){const s=(t=>{let e,s,n,i,r,o=.75*t.length,a=t.length,c=0;"="===t[t.length-1]&&(o--,"="===t[t.length-2]&&o--);const h=new ArrayBuffer(o),u=new Uint8Array(h);for(e=0;e<a;e+=4)s=f[t.charCodeAt(e)],n=f[t.charCodeAt(e+1)],i=f[t.charCodeAt(e+2)],r=f[t.charCodeAt(e+3)],u[c++]=s<<2|n>>4,u[c++]=(15&n)<<4|i>>2,u[c++]=(3&i)<<6|63&r;return h})(t);return _(s,e)}return{base64:!0,data:t}},_=(t,e)=>"blob"===e?t instanceof Blob?t:new Blob([t]):t instanceof ArrayBuffer?t:t.buffer,b=String.fromCharCode(30);let v;function w(t){return t.reduce((t,e)=>t+e.length,0)}function k(t,e){if(t[0].length===e)return t.shift();const s=new Uint8Array(e);let n=0;for(let i=0;i<e;i++)s[i]=t[0][n++],n===t[0].length&&(t.shift(),n=0);return t.length&&n<t[0].length&&(t[0]=t[0].slice(n)),s}function E(t){if(t)return function(t){for(var e in E.prototype)t[e]=E.prototype[e];return t}(t)}E.prototype.on=E.prototype.addEventListener=function(t,e){return this._callbacks=this._callbacks||{},(this._callbacks["$"+t]=this._callbacks["$"+t]||[]).push(e),this},E.prototype.once=function(t,e){function s(){this.off(t,s),e.apply(this,arguments)}return s.fn=e,this.on(t,s),this},E.prototype.off=E.prototype.removeListener=E.prototype.removeAllListeners=E.prototype.removeEventListener=function(t,e){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var s,n=this._callbacks["$"+t];if(!n)return this;if(1==arguments.length)return delete this._callbacks["$"+t],this;for(var i=0;i<n.length;i++)if((s=n[i])===e||s.fn===e){n.splice(i,1);break}return 0===n.length&&delete this._callbacks["$"+t],this},E.prototype.emit=function(t){this._callbacks=this._callbacks||{};for(var e=new Array(arguments.length-1),s=this._callbacks["$"+t],n=1;n<arguments.length;n++)e[n-1]=arguments[n];if(s){n=0;for(var i=(s=s.slice(0)).length;n<i;++n)s[n].apply(this,e)}return this},E.prototype.emitReserved=E.prototype.emit,E.prototype.listeners=function(t){return this._callbacks=this._callbacks||{},this._callbacks["$"+t]||[]},E.prototype.hasListeners=function(t){return!!this.listeners(t).length};const C="function"==typeof Promise&&"function"==typeof Promise.resolve?t=>Promise.resolve().then(t):(t,e)=>e(t,0),T="undefined"!=typeof self?self:"undefined"!=typeof window?window:Function("return this")();function A(t,...e){return e.reduce((e,s)=>(t.hasOwnProperty(s)&&(e[s]=t[s]),e),{})}const O=T.setTimeout,R=T.clearTimeout;function S(t,e){e.useNativeTimers?(t.setTimeoutFn=O.bind(T),t.clearTimeoutFn=R.bind(T)):(t.setTimeoutFn=T.setTimeout.bind(T),t.clearTimeoutFn=T.clearTimeout.bind(T))}function B(t){return"string"==typeof t?function(t){let e=0,s=0;for(let n=0,i=t.length;n<i;n++)e=t.charCodeAt(n),e<128?s+=1:e<2048?s+=2:e<55296||e>=57344?s+=3:(n++,s+=4);return s}(t):Math.ceil(1.33*(t.byteLength||t.size))}function x(){return Date.now().toString(36).substring(3)+Math.random().toString(36).substring(2,5)}class L extends Error{constructor(t,e,s){super(t),this.description=e,this.context=s,this.type="TransportError"}}class N extends E{constructor(t){super(),this.writable=!1,S(this,t),this.opts=t,this.query=t.query,this.socket=t.socket,this.supportsBinary=!t.forceBase64}onError(t,e,s){return super.emitReserved("error",new L(t,e,s)),this}open(){return this.readyState="opening",this.doOpen(),this}close(){return"opening"!==this.readyState&&"open"!==this.readyState||(this.doClose(),this.onClose()),this}send(t){"open"===this.readyState&&this.write(t)}onOpen(){this.readyState="open",this.writable=!0,super.emitReserved("open")}onData(t){const e=g(t,this.socket.binaryType);this.onPacket(e)}onPacket(t){super.emitReserved("packet",t)}onClose(t){this.readyState="closed",super.emitReserved("close",t)}pause(t){}createUri(t,e={}){return t+"://"+this._hostname()+this._port()+this.opts.path+this._query(e)}_hostname(){const t=this.opts.hostname;return-1===t.indexOf(":")?t:"["+t+"]"}_port(){return this.opts.port&&(this.opts.secure&&Number(443!==this.opts.port)||!this.opts.secure&&80!==Number(this.opts.port))?":"+this.opts.port:""}_query(t){const e=function(t){let e="";for(let s in t)t.hasOwnProperty(s)&&(e.length&&(e+="&"),e+=encodeURIComponent(s)+"="+encodeURIComponent(t[s]));return e}(t);return e.length?"?"+e:""}}class P extends N{constructor(){super(...arguments),this._polling=!1}get name(){return"polling"}doOpen(){this._poll()}pause(t){this.readyState="pausing";const e=()=>{this.readyState="paused",t()};if(this._polling||!this.writable){let t=0;this._polling&&(t++,this.once("pollComplete",function(){--t||e()})),this.writable||(t++,this.once("drain",function(){--t||e()}))}else e()}_poll(){this._polling=!0,this.doPoll(),this.emitReserved("poll")}onData(t){((t,e)=>{const s=t.split(b),n=[];for(let t=0;t<s.length;t++){const i=g(s[t],e);if(n.push(i),"error"===i.type)break}return n})(t,this.socket.binaryType).forEach(t=>{if("opening"===this.readyState&&"open"===t.type&&this.onOpen(),"close"===t.type)return this.onClose({description:"transport closed by the server"}),!1;this.onPacket(t)}),"closed"!==this.readyState&&(this._polling=!1,this.emitReserved("pollComplete"),"open"===this.readyState&&this._poll())}doClose(){const t=()=>{this.write([{type:"close"}])};"open"===this.readyState?t():this.once("open",t)}write(t){this.writable=!1,((t,e)=>{const s=t.length,n=new Array(s);let i=0;t.forEach((t,r)=>{u(t,!1,t=>{n[r]=t,++i===s&&e(n.join(b))})})})(t,t=>{this.doWrite(t,()=>{this.writable=!0,this.emitReserved("drain")})})}uri(){const t=this.opts.secure?"https":"http",e=this.query||{};return!1!==this.opts.timestampRequests&&(e[this.opts.timestampParam]=x()),this.supportsBinary||e.sid||(e.b64=1),this.createUri(t,e)}}let q=!1;try{q="undefined"!=typeof XMLHttpRequest&&"withCredentials"in new XMLHttpRequest}catch(t){}const j=q;function I(){}class D extends P{constructor(t){if(super(t),"undefined"!=typeof location){const e="https:"===location.protocol;let s=location.port;s||(s=e?"443":"80"),this.xd="undefined"!=typeof location&&t.hostname!==location.hostname||s!==t.port}}doWrite(t,e){const s=this.request({method:"POST",data:t});s.on("success",e),s.on("error",(t,e)=>{this.onError("xhr post error",t,e)})}doPoll(){const t=this.request();t.on("data",this.onData.bind(this)),t.on("error",(t,e)=>{this.onError("xhr poll error",t,e)}),this.pollXhr=t}}class U extends E{constructor(t,e,s){super(),this.createRequest=t,S(this,s),this._opts=s,this._method=s.method||"GET",this._uri=e,this._data=void 0!==s.data?s.data:null,this._create()}_create(){var t;const e=A(this._opts,"agent","pfx","key","passphrase","cert","ca","ciphers","rejectUnauthorized","autoUnref");e.xdomain=!!this._opts.xd;const s=this._xhr=this.createRequest(e);try{s.open(this._method,this._uri,!0);try{if(this._opts.extraHeaders){s.setDisableHeaderCheck&&s.setDisableHeaderCheck(!0);for(let t in this._opts.extraHeaders)this._opts.extraHeaders.hasOwnProperty(t)&&s.setRequestHeader(t,this._opts.extraHeaders[t])}}catch(t){}if("POST"===this._method)try{s.setRequestHeader("Content-type","text/plain;charset=UTF-8")}catch(t){}try{s.setRequestHeader("Accept","*/*")}catch(t){}null===(t=this._opts.cookieJar)||void 0===t||t.addCookies(s),"withCredentials"in s&&(s.withCredentials=this._opts.withCredentials),this._opts.requestTimeout&&(s.timeout=this._opts.requestTimeout),s.onreadystatechange=()=>{var t;3===s.readyState&&(null===(t=this._opts.cookieJar)||void 0===t||t.parseCookies(s.getResponseHeader("set-cookie"))),4===s.readyState&&(200===s.status||1223===s.status?this._onLoad():this.setTimeoutFn(()=>{this._onError("number"==typeof s.status?s.status:0)},0))},s.send(this._data)}catch(t){return void this.setTimeoutFn(()=>{this._onError(t)},0)}"undefined"!=typeof document&&(this._index=U.requestsCount++,U.requests[this._index]=this)}_onError(t){this.emitReserved("error",t,this._xhr),this._cleanup(!0)}_cleanup(t){if(void 0!==this._xhr&&null!==this._xhr){if(this._xhr.onreadystatechange=I,t)try{this._xhr.abort()}catch(t){}"undefined"!=typeof document&&delete U.requests[this._index],this._xhr=null}}_onLoad(){const t=this._xhr.responseText;null!==t&&(this.emitReserved("data",t),this.emitReserved("success"),this._cleanup())}abort(){this._cleanup()}}function M(){for(let t in U.requests)U.requests.hasOwnProperty(t)&&U.requests[t].abort()}U.requestsCount=0,U.requests={},"undefined"!=typeof document&&("function"==typeof attachEvent?attachEvent("onunload",M):"function"==typeof addEventListener&&addEventListener("onpagehide"in T?"pagehide":"unload",M,!1));const F=function(){const t=V({xdomain:!1});return t&&null!==t.responseType}();function V(t){const e=t.xdomain;try{if("undefined"!=typeof XMLHttpRequest&&(!e||j))return new XMLHttpRequest}catch(t){}if(!e)try{return new(T[["Active"].concat("Object").join("X")])("Microsoft.XMLHTTP")}catch(t){}}const H="undefined"!=typeof navigator&&"string"==typeof navigator.product&&"reactnative"===navigator.product.toLowerCase();class K extends N{get name(){return"websocket"}doOpen(){const t=this.uri(),e=this.opts.protocols,s=H?{}:A(this.opts,"agent","perMessageDeflate","pfx","key","passphrase","cert","ca","ciphers","rejectUnauthorized","localAddress","protocolVersion","origin","maxPayload","family","checkServerIdentity");this.opts.extraHeaders&&(s.headers=this.opts.extraHeaders);try{this.ws=this.createSocket(t,e,s)}catch(t){return this.emitReserved("error",t)}this.ws.binaryType=this.socket.binaryType,this.addEventListeners()}addEventListeners(){this.ws.onopen=()=>{this.opts.autoUnref&&this.ws._socket.unref(),this.onOpen()},this.ws.onclose=t=>this.onClose({description:"websocket connection closed",context:t}),this.ws.onmessage=t=>this.onData(t.data),this.ws.onerror=t=>this.onError("websocket error",t)}write(t){this.writable=!1;for(let e=0;e<t.length;e++){const s=t[e],n=e===t.length-1;u(s,this.supportsBinary,t=>{try{this.doWrite(s,t)}catch(t){}n&&C(()=>{this.writable=!0,this.emitReserved("drain")},this.setTimeoutFn)})}}doClose(){void 0!==this.ws&&(this.ws.onerror=()=>{},this.ws.close(),this.ws=null)}uri(){const t=this.opts.secure?"wss":"ws",e=this.query||{};return this.opts.timestampRequests&&(e[this.opts.timestampParam]=x()),this.supportsBinary||(e.b64=1),this.createUri(t,e)}}const $=T.WebSocket||T.MozWebSocket,W={websocket:class extends K{createSocket(t,e,s){return H?new $(t,e,s):e?new $(t,e):new $(t)}doWrite(t,e){this.ws.send(e)}},webtransport:class extends N{get name(){return"webtransport"}doOpen(){try{this._transport=new WebTransport(this.createUri("https"),this.opts.transportOptions[this.name])}catch(t){return this.emitReserved("error",t)}this._transport.closed.then(()=>{this.onClose()}).catch(t=>{this.onError("webtransport error",t)}),this._transport.ready.then(()=>{this._transport.createBidirectionalStream().then(t=>{const e=function(t,e){v||(v=new TextDecoder);const s=[];let n=0,i=-1,r=!1;return new TransformStream({transform(a,c){for(s.push(a);;){if(0===n){if(w(s)<1)break;const t=k(s,1);r=!(128&~t[0]),i=127&t[0],n=i<126?3:126===i?1:2}else if(1===n){if(w(s)<2)break;const t=k(s,2);i=new DataView(t.buffer,t.byteOffset,t.length).getUint16(0),n=3}else if(2===n){if(w(s)<8)break;const t=k(s,8),e=new DataView(t.buffer,t.byteOffset,t.length),r=e.getUint32(0);if(r>Math.pow(2,21)-1){c.enqueue(o);break}i=r*Math.pow(2,32)+e.getUint32(4),n=3}else{if(w(s)<i)break;const t=k(s,i);c.enqueue(g(r?t:v.decode(t),e)),n=0}if(0===i||i>t){c.enqueue(o);break}}}})}(Number.MAX_SAFE_INTEGER,this.socket.binaryType),s=t.readable.pipeThrough(e).getReader(),n=new TransformStream({transform(t,e){!function(t,e){a&&t.data instanceof Blob?t.data.arrayBuffer().then(d).then(e):c&&(t.data instanceof ArrayBuffer||h(t.data))?e(d(t.data)):u(t,!1,t=>{l||(l=new TextEncoder),e(l.encode(t))})}(t,s=>{const n=s.length;let i;if(n<126)i=new Uint8Array(1),new DataView(i.buffer).setUint8(0,n);else if(n<65536){i=new Uint8Array(3);const t=new DataView(i.buffer);t.setUint8(0,126),t.setUint16(1,n)}else{i=new Uint8Array(9);const t=new DataView(i.buffer);t.setUint8(0,127),t.setBigUint64(1,BigInt(n))}t.data&&"string"!=typeof t.data&&(i[0]|=128),e.enqueue(i),e.enqueue(s)})}});n.readable.pipeTo(t.writable),this._writer=n.writable.getWriter();const i=()=>{s.read().then(({done:t,value:e})=>{t||(this.onPacket(e),i())}).catch(t=>{})};i();const r={type:"open"};this.query.sid&&(r.data=`{"sid":"${this.query.sid}"}`),this._writer.write(r).then(()=>this.onOpen())})})}write(t){this.writable=!1;for(let e=0;e<t.length;e++){const s=t[e],n=e===t.length-1;this._writer.write(s).then(()=>{n&&C(()=>{this.writable=!0,this.emitReserved("drain")},this.setTimeoutFn)})}}doClose(){var t;null===(t=this._transport)||void 0===t||t.close()}},polling:class extends D{constructor(t){super(t);const e=t&&t.forceBase64;this.supportsBinary=F&&!e}request(t={}){return Object.assign(t,{xd:this.xd},this.opts),new U(V,this.uri(),t)}}},Y=/^(?:(?![^:@\/?#]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@\/?#]*)(?::([^:@\/?#]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/,z=["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"];function J(t){if(t.length>8e3)throw"URI too long";const e=t,s=t.indexOf("["),n=t.indexOf("]");-1!=s&&-1!=n&&(t=t.substring(0,s)+t.substring(s,n).replace(/:/g,";")+t.substring(n,t.length));let i=Y.exec(t||""),r={},o=14;for(;o--;)r[z[o]]=i[o]||"";return-1!=s&&-1!=n&&(r.source=e,r.host=r.host.substring(1,r.host.length-1).replace(/;/g,":"),r.authority=r.authority.replace("[","").replace("]","").replace(/;/g,":"),r.ipv6uri=!0),r.pathNames=function(t,e){const s=e.replace(/\/{2,9}/g,"/").split("/");return"/"!=e.slice(0,1)&&0!==e.length||s.splice(0,1),"/"==e.slice(-1)&&s.splice(s.length-1,1),s}(0,r.path),r.queryKey=function(t,e){const s={};return e.replace(/(?:^|&)([^&=]*)=?([^&]*)/g,function(t,e,n){e&&(s[e]=n)}),s}(0,r.query),r}const Q="function"==typeof addEventListener&&"function"==typeof removeEventListener,X=[];Q&&addEventListener("offline",()=>{X.forEach(t=>t())},!1);class G extends E{constructor(t,e){if(super(),this.binaryType="arraybuffer",this.writeBuffer=[],this._prevBufferLen=0,this._pingInterval=-1,this._pingTimeout=-1,this._maxPayload=-1,this._pingTimeoutTime=1/0,t&&"object"==typeof t&&(e=t,t=null),t){const s=J(t);e.hostname=s.host,e.secure="https"===s.protocol||"wss"===s.protocol,e.port=s.port,s.query&&(e.query=s.query)}else e.host&&(e.hostname=J(e.host).host);S(this,e),this.secure=null!=e.secure?e.secure:"undefined"!=typeof location&&"https:"===location.protocol,e.hostname&&!e.port&&(e.port=this.secure?"443":"80"),this.hostname=e.hostname||("undefined"!=typeof location?location.hostname:"localhost"),this.port=e.port||("undefined"!=typeof location&&location.port?location.port:this.secure?"443":"80"),this.transports=[],this._transportsByName={},e.transports.forEach(t=>{const e=t.prototype.name;this.transports.push(e),this._transportsByName[e]=t}),this.opts=Object.assign({path:"/engine.io",agent:!1,withCredentials:!1,upgrade:!0,timestampParam:"t",rememberUpgrade:!1,addTrailingSlash:!0,rejectUnauthorized:!0,perMessageDeflate:{threshold:1024},transportOptions:{},closeOnBeforeunload:!1},e),this.opts.path=this.opts.path.replace(/\/$/,"")+(this.opts.addTrailingSlash?"/":""),"string"==typeof this.opts.query&&(this.opts.query=function(t){let e={},s=t.split("&");for(let t=0,n=s.length;t<n;t++){let n=s[t].split("=");e[decodeURIComponent(n[0])]=decodeURIComponent(n[1])}return e}(this.opts.query)),Q&&(this.opts.closeOnBeforeunload&&(this._beforeunloadEventListener=()=>{this.transport&&(this.transport.removeAllListeners(),this.transport.close())},addEventListener("beforeunload",this._beforeunloadEventListener,!1)),"localhost"!==this.hostname&&(this._offlineEventListener=()=>{this._onClose("transport close",{description:"network connection lost"})},X.push(this._offlineEventListener))),this.opts.withCredentials&&(this._cookieJar=void 0),this._open()}createTransport(t){const e=Object.assign({},this.opts.query);e.EIO=4,e.transport=t,this.id&&(e.sid=this.id);const s=Object.assign({},this.opts,{query:e,socket:this,hostname:this.hostname,secure:this.secure,port:this.port},this.opts.transportOptions[t]);return new this._transportsByName[t](s)}_open(){if(0===this.transports.length)return void this.setTimeoutFn(()=>{this.emitReserved("error","No transports available")},0);const t=this.opts.rememberUpgrade&&G.priorWebsocketSuccess&&-1!==this.transports.indexOf("websocket")?"websocket":this.transports[0];this.readyState="opening";const e=this.createTransport(t);e.open(),this.setTransport(e)}setTransport(t){this.transport&&this.transport.removeAllListeners(),this.transport=t,t.on("drain",this._onDrain.bind(this)).on("packet",this._onPacket.bind(this)).on("error",this._onError.bind(this)).on("close",t=>this._onClose("transport close",t))}onOpen(){this.readyState="open",G.priorWebsocketSuccess="websocket"===this.transport.name,this.emitReserved("open"),this.flush()}_onPacket(t){if("opening"===this.readyState||"open"===this.readyState||"closing"===this.readyState)switch(this.emitReserved("packet",t),this.emitReserved("heartbeat"),t.type){case"open":this.onHandshake(JSON.parse(t.data));break;case"ping":this._sendPacket("pong"),this.emitReserved("ping"),this.emitReserved("pong"),this._resetPingTimeout();break;case"error":const e=new Error("server error");e.code=t.data,this._onError(e);break;case"message":this.emitReserved("data",t.data),this.emitReserved("message",t.data)}}onHandshake(t){this.emitReserved("handshake",t),this.id=t.sid,this.transport.query.sid=t.sid,this._pingInterval=t.pingInterval,this._pingTimeout=t.pingTimeout,this._maxPayload=t.maxPayload,this.onOpen(),"closed"!==this.readyState&&this._resetPingTimeout()}_resetPingTimeout(){this.clearTimeoutFn(this._pingTimeoutTimer);const t=this._pingInterval+this._pingTimeout;this._pingTimeoutTime=Date.now()+t,this._pingTimeoutTimer=this.setTimeoutFn(()=>{this._onClose("ping timeout")},t),this.opts.autoUnref&&this._pingTimeoutTimer.unref()}_onDrain(){this.writeBuffer.splice(0,this._prevBufferLen),this._prevBufferLen=0,0===this.writeBuffer.length?this.emitReserved("drain"):this.flush()}flush(){if("closed"!==this.readyState&&this.transport.writable&&!this.upgrading&&this.writeBuffer.length){const t=this._getWritablePackets();this.transport.send(t),this._prevBufferLen=t.length,this.emitReserved("flush")}}_getWritablePackets(){if(!(this._maxPayload&&"polling"===this.transport.name&&this.writeBuffer.length>1))return this.writeBuffer;let t=1;for(let e=0;e<this.writeBuffer.length;e++){const s=this.writeBuffer[e].data;if(s&&(t+=B(s)),e>0&&t>this._maxPayload)return this.writeBuffer.slice(0,e);t+=2}return this.writeBuffer}_hasPingExpired(){if(!this._pingTimeoutTime)return!0;const t=Date.now()>this._pingTimeoutTime;return t&&(this._pingTimeoutTime=0,C(()=>{this._onClose("ping timeout")},this.setTimeoutFn)),t}write(t,e,s){return this._sendPacket("message",t,e,s),this}send(t,e,s){return this._sendPacket("message",t,e,s),this}_sendPacket(t,e,s,n){if("function"==typeof e&&(n=e,e=void 0),"function"==typeof s&&(n=s,s=null),"closing"===this.readyState||"closed"===this.readyState)return;(s=s||{}).compress=!1!==s.compress;const i={type:t,data:e,options:s};this.emitReserved("packetCreate",i),this.writeBuffer.push(i),n&&this.once("flush",n),this.flush()}close(){const t=()=>{this._onClose("forced close"),this.transport.close()},e=()=>{this.off("upgrade",e),this.off("upgradeError",e),t()},s=()=>{this.once("upgrade",e),this.once("upgradeError",e)};return"opening"!==this.readyState&&"open"!==this.readyState||(this.readyState="closing",this.writeBuffer.length?this.once("drain",()=>{this.upgrading?s():t()}):this.upgrading?s():t()),this}_onError(t){if(G.priorWebsocketSuccess=!1,this.opts.tryAllTransports&&this.transports.length>1&&"opening"===this.readyState)return this.transports.shift(),this._open();this.emitReserved("error",t),this._onClose("transport error",t)}_onClose(t,e){if("opening"===this.readyState||"open"===this.readyState||"closing"===this.readyState){if(this.clearTimeoutFn(this._pingTimeoutTimer),this.transport.removeAllListeners("close"),this.transport.close(),this.transport.removeAllListeners(),Q&&(this._beforeunloadEventListener&&removeEventListener("beforeunload",this._beforeunloadEventListener,!1),this._offlineEventListener)){const t=X.indexOf(this._offlineEventListener);-1!==t&&X.splice(t,1)}this.readyState="closed",this.id=null,this.emitReserved("close",t,e),this.writeBuffer=[],this._prevBufferLen=0}}}G.protocol=4;class Z extends G{constructor(){super(...arguments),this._upgrades=[]}onOpen(){if(super.onOpen(),"open"===this.readyState&&this.opts.upgrade)for(let t=0;t<this._upgrades.length;t++)this._probe(this._upgrades[t])}_probe(t){let e=this.createTransport(t),s=!1;G.priorWebsocketSuccess=!1;const n=()=>{s||(e.send([{type:"ping",data:"probe"}]),e.once("packet",t=>{if(!s)if("pong"===t.type&&"probe"===t.data){if(this.upgrading=!0,this.emitReserved("upgrading",e),!e)return;G.priorWebsocketSuccess="websocket"===e.name,this.transport.pause(()=>{s||"closed"!==this.readyState&&(h(),this.setTransport(e),e.send([{type:"upgrade"}]),this.emitReserved("upgrade",e),e=null,this.upgrading=!1,this.flush())})}else{const t=new Error("probe error");t.transport=e.name,this.emitReserved("upgradeError",t)}}))};function i(){s||(s=!0,h(),e.close(),e=null)}const r=t=>{const s=new Error("probe error: "+t);s.transport=e.name,i(),this.emitReserved("upgradeError",s)};function o(){r("transport closed")}function a(){r("socket closed")}function c(t){e&&t.name!==e.name&&i()}const h=()=>{e.removeListener("open",n),e.removeListener("error",r),e.removeListener("close",o),this.off("close",a),this.off("upgrading",c)};e.once("open",n),e.once("error",r),e.once("close",o),this.once("close",a),this.once("upgrading",c),-1!==this._upgrades.indexOf("webtransport")&&"webtransport"!==t?this.setTimeoutFn(()=>{s||e.open()},200):e.open()}onHandshake(t){this._upgrades=this._filterUpgrades(t.upgrades),super.onHandshake(t)}_filterUpgrades(t){const e=[];for(let s=0;s<t.length;s++)~this.transports.indexOf(t[s])&&e.push(t[s]);return e}}class tt extends Z{constructor(t,e={}){const s="object"==typeof t?t:e;(!s.transports||s.transports&&"string"==typeof s.transports[0])&&(s.transports=(s.transports||["polling","websocket","webtransport"]).map(t=>W[t]).filter(t=>!!t)),super(t,s)}}const et="function"==typeof ArrayBuffer,st=Object.prototype.toString,nt="function"==typeof Blob||"undefined"!=typeof Blob&&"[object BlobConstructor]"===st.call(Blob),it="function"==typeof File||"undefined"!=typeof File&&"[object FileConstructor]"===st.call(File);function rt(t){return et&&(t instanceof ArrayBuffer||(t=>"function"==typeof ArrayBuffer.isView?ArrayBuffer.isView(t):t.buffer instanceof ArrayBuffer)(t))||nt&&t instanceof Blob||it&&t instanceof File}function ot(t,e){if(!t||"object"!=typeof t)return!1;if(Array.isArray(t)){for(let e=0,s=t.length;e<s;e++)if(ot(t[e]))return!0;return!1}if(rt(t))return!0;if(t.toJSON&&"function"==typeof t.toJSON&&1===arguments.length)return ot(t.toJSON(),!0);for(const e in t)if(Object.prototype.hasOwnProperty.call(t,e)&&ot(t[e]))return!0;return!1}function at(t){const e=[],s=t.data,n=t;return n.data=ct(s,e),n.attachments=e.length,{packet:n,buffers:e}}function ct(t,e){if(!t)return t;if(rt(t)){const s={_placeholder:!0,num:e.length};return e.push(t),s}if(Array.isArray(t)){const s=new Array(t.length);for(let n=0;n<t.length;n++)s[n]=ct(t[n],e);return s}if("object"==typeof t&&!(t instanceof Date)){const s={};for(const n in t)Object.prototype.hasOwnProperty.call(t,n)&&(s[n]=ct(t[n],e));return s}return t}function ht(t,e){return t.data=ut(t.data,e),delete t.attachments,t}function ut(t,e){if(!t)return t;if(t&&!0===t._placeholder){if("number"==typeof t.num&&t.num>=0&&t.num<e.length)return e[t.num];throw new Error("illegal attachments")}if(Array.isArray(t))for(let s=0;s<t.length;s++)t[s]=ut(t[s],e);else if("object"==typeof t)for(const s in t)Object.prototype.hasOwnProperty.call(t,s)&&(t[s]=ut(t[s],e));return t}const pt=["connect","connect_error","disconnect","disconnecting","newListener","removeListener"],dt=5;var lt;!function(t){t[t.CONNECT=0]="CONNECT",t[t.DISCONNECT=1]="DISCONNECT",t[t.EVENT=2]="EVENT",t[t.ACK=3]="ACK",t[t.CONNECT_ERROR=4]="CONNECT_ERROR",t[t.BINARY_EVENT=5]="BINARY_EVENT",t[t.BINARY_ACK=6]="BINARY_ACK"}(lt||(lt={}));class ft{constructor(t){this.replacer=t}encode(t){return t.type!==lt.EVENT&&t.type!==lt.ACK||!ot(t)?[this.encodeAsString(t)]:this.encodeAsBinary({type:t.type===lt.EVENT?lt.BINARY_EVENT:lt.BINARY_ACK,nsp:t.nsp,data:t.data,id:t.id})}encodeAsString(t){let e=""+t.type;return t.type!==lt.BINARY_EVENT&&t.type!==lt.BINARY_ACK||(e+=t.attachments+"-"),t.nsp&&"/"!==t.nsp&&(e+=t.nsp+","),null!=t.id&&(e+=t.id),null!=t.data&&(e+=JSON.stringify(t.data,this.replacer)),e}encodeAsBinary(t){const e=at(t),s=this.encodeAsString(e.packet),n=e.buffers;return n.unshift(s),n}}function yt(t){return"[object Object]"===Object.prototype.toString.call(t)}class gt extends E{constructor(t){super(),this.reviver=t}add(t){let e;if("string"==typeof t){if(this.reconstructor)throw new Error("got plaintext data when reconstructing a packet");e=this.decodeString(t);const s=e.type===lt.BINARY_EVENT;s||e.type===lt.BINARY_ACK?(e.type=s?lt.EVENT:lt.ACK,this.reconstructor=new mt(e),0===e.attachments&&super.emitReserved("decoded",e)):super.emitReserved("decoded",e)}else{if(!rt(t)&&!t.base64)throw new Error("Unknown type: "+t);if(!this.reconstructor)throw new Error("got binary data when not reconstructing a packet");e=this.reconstructor.takeBinaryData(t),e&&(this.reconstructor=null,super.emitReserved("decoded",e))}}decodeString(t){let e=0;const s={type:Number(t.charAt(0))};if(void 0===lt[s.type])throw new Error("unknown packet type "+s.type);if(s.type===lt.BINARY_EVENT||s.type===lt.BINARY_ACK){const n=e+1;for(;"-"!==t.charAt(++e)&&e!=t.length;);const i=t.substring(n,e);if(i!=Number(i)||"-"!==t.charAt(e))throw new Error("Illegal attachments");s.attachments=Number(i)}if("/"===t.charAt(e+1)){const n=e+1;for(;++e&&","!==t.charAt(e)&&e!==t.length;);s.nsp=t.substring(n,e)}else s.nsp="/";const n=t.charAt(e+1);if(""!==n&&Number(n)==n){const n=e+1;for(;++e;){const s=t.charAt(e);if(null==s||Number(s)!=s){--e;break}if(e===t.length)break}s.id=Number(t.substring(n,e+1))}if(t.charAt(++e)){const n=this.tryParse(t.substr(e));if(!gt.isPayloadValid(s.type,n))throw new Error("invalid payload");s.data=n}return s}tryParse(t){try{return JSON.parse(t,this.reviver)}catch(t){return!1}}static isPayloadValid(t,e){switch(t){case lt.CONNECT:return yt(e);case lt.DISCONNECT:return void 0===e;case lt.CONNECT_ERROR:return"string"==typeof e||yt(e);case lt.EVENT:case lt.BINARY_EVENT:return Array.isArray(e)&&("number"==typeof e[0]||"string"==typeof e[0]&&-1===pt.indexOf(e[0]));case lt.ACK:case lt.BINARY_ACK:return Array.isArray(e)}}destroy(){this.reconstructor&&(this.reconstructor.finishedReconstruction(),this.reconstructor=null)}}class mt{constructor(t){this.packet=t,this.buffers=[],this.reconPack=t}takeBinaryData(t){if(this.buffers.push(t),this.buffers.length===this.reconPack.attachments){const t=ht(this.reconPack,this.buffers);return this.finishedReconstruction(),t}return null}finishedReconstruction(){this.reconPack=null,this.buffers=[]}}function _t(t,e,s){return t.on(e,s),function(){t.off(e,s)}}const bt=Object.freeze({connect:1,connect_error:1,disconnect:1,disconnecting:1,newListener:1,removeListener:1});class vt extends E{constructor(t,e,s){super(),this.connected=!1,this.recovered=!1,this.receiveBuffer=[],this.sendBuffer=[],this._queue=[],this._queueSeq=0,this.ids=0,this.acks={},this.flags={},this.io=t,this.nsp=e,s&&s.auth&&(this.auth=s.auth),this._opts=Object.assign({},s),this.io._autoConnect&&this.open()}get disconnected(){return!this.connected}subEvents(){if(this.subs)return;const t=this.io;this.subs=[_t(t,"open",this.onopen.bind(this)),_t(t,"packet",this.onpacket.bind(this)),_t(t,"error",this.onerror.bind(this)),_t(t,"close",this.onclose.bind(this))]}get active(){return!!this.subs}connect(){return this.connected||(this.subEvents(),this.io._reconnecting||this.io.open(),"open"===this.io._readyState&&this.onopen()),this}open(){return this.connect()}send(...t){return t.unshift("message"),this.emit.apply(this,t),this}emit(t,...e){var s,n,i;if(bt.hasOwnProperty(t))throw new Error('"'+t.toString()+'" is a reserved event name');if(e.unshift(t),this._opts.retries&&!this.flags.fromQueue&&!this.flags.volatile)return this._addToQueue(e),this;const r={type:lt.EVENT,data:e,options:{}};if(r.options.compress=!1!==this.flags.compress,"function"==typeof e[e.length-1]){const t=this.ids++,s=e.pop();this._registerAckCallback(t,s),r.id=t}const o=null===(n=null===(s=this.io.engine)||void 0===s?void 0:s.transport)||void 0===n?void 0:n.writable,a=this.connected&&!(null===(i=this.io.engine)||void 0===i?void 0:i._hasPingExpired());return this.flags.volatile&&!o||(a?(this.notifyOutgoingListeners(r),this.packet(r)):this.sendBuffer.push(r)),this.flags={},this}_registerAckCallback(t,e){var s;const n=null!==(s=this.flags.timeout)&&void 0!==s?s:this._opts.ackTimeout;if(void 0===n)return void(this.acks[t]=e);const i=this.io.setTimeoutFn(()=>{delete this.acks[t];for(let e=0;e<this.sendBuffer.length;e++)this.sendBuffer[e].id===t&&this.sendBuffer.splice(e,1);e.call(this,new Error("operation has timed out"))},n),r=(...t)=>{this.io.clearTimeoutFn(i),e.apply(this,t)};r.withError=!0,this.acks[t]=r}emitWithAck(t,...e){return new Promise((s,n)=>{const i=(t,e)=>t?n(t):s(e);i.withError=!0,e.push(i),this.emit(t,...e)})}_addToQueue(t){let e;"function"==typeof t[t.length-1]&&(e=t.pop());const s={id:this._queueSeq++,tryCount:0,pending:!1,args:t,flags:Object.assign({fromQueue:!0},this.flags)};t.push((t,...n)=>{if(s===this._queue[0])return null!==t?s.tryCount>this._opts.retries&&(this._queue.shift(),e&&e(t)):(this._queue.shift(),e&&e(null,...n)),s.pending=!1,this._drainQueue()}),this._queue.push(s),this._drainQueue()}_drainQueue(t=!1){if(!this.connected||0===this._queue.length)return;const e=this._queue[0];e.pending&&!t||(e.pending=!0,e.tryCount++,this.flags=e.flags,this.emit.apply(this,e.args))}packet(t){t.nsp=this.nsp,this.io._packet(t)}onopen(){"function"==typeof this.auth?this.auth(t=>{this._sendConnectPacket(t)}):this._sendConnectPacket(this.auth)}_sendConnectPacket(t){this.packet({type:lt.CONNECT,data:this._pid?Object.assign({pid:this._pid,offset:this._lastOffset},t):t})}onerror(t){this.connected||this.emitReserved("connect_error",t)}onclose(t,e){this.connected=!1,delete this.id,this.emitReserved("disconnect",t,e),this._clearAcks()}_clearAcks(){Object.keys(this.acks).forEach(t=>{if(!this.sendBuffer.some(e=>String(e.id)===t)){const e=this.acks[t];delete this.acks[t],e.withError&&e.call(this,new Error("socket has been disconnected"))}})}onpacket(t){if(t.nsp===this.nsp)switch(t.type){case lt.CONNECT:t.data&&t.data.sid?this.onconnect(t.data.sid,t.data.pid):this.emitReserved("connect_error",new Error("It seems you are trying to reach a Socket.IO server in v2.x with a v3.x client, but they are not compatible (more information here: https://socket.io/docs/v3/migrating-from-2-x-to-3-0/)"));break;case lt.EVENT:case lt.BINARY_EVENT:this.onevent(t);break;case lt.ACK:case lt.BINARY_ACK:this.onack(t);break;case lt.DISCONNECT:this.ondisconnect();break;case lt.CONNECT_ERROR:this.destroy();const e=new Error(t.data.message);e.data=t.data.data,this.emitReserved("connect_error",e)}}onevent(t){const e=t.data||[];null!=t.id&&e.push(this.ack(t.id)),this.connected?this.emitEvent(e):this.receiveBuffer.push(Object.freeze(e))}emitEvent(t){if(this._anyListeners&&this._anyListeners.length){const e=this._anyListeners.slice();for(const s of e)s.apply(this,t)}super.emit.apply(this,t),this._pid&&t.length&&"string"==typeof t[t.length-1]&&(this._lastOffset=t[t.length-1])}ack(t){const e=this;let s=!1;return function(...n){s||(s=!0,e.packet({type:lt.ACK,id:t,data:n}))}}onack(t){const e=this.acks[t.id];"function"==typeof e&&(delete this.acks[t.id],e.withError&&t.data.unshift(null),e.apply(this,t.data))}onconnect(t,e){this.id=t,this.recovered=e&&this._pid===e,this._pid=e,this.connected=!0,this.emitBuffered(),this.emitReserved("connect"),this._drainQueue(!0)}emitBuffered(){this.receiveBuffer.forEach(t=>this.emitEvent(t)),this.receiveBuffer=[],this.sendBuffer.forEach(t=>{this.notifyOutgoingListeners(t),this.packet(t)}),this.sendBuffer=[]}ondisconnect(){this.destroy(),this.onclose("io server disconnect")}destroy(){this.subs&&(this.subs.forEach(t=>t()),this.subs=void 0),this.io._destroy(this)}disconnect(){return this.connected&&this.packet({type:lt.DISCONNECT}),this.destroy(),this.connected&&this.onclose("io client disconnect"),this}close(){return this.disconnect()}compress(t){return this.flags.compress=t,this}get volatile(){return this.flags.volatile=!0,this}timeout(t){return this.flags.timeout=t,this}onAny(t){return this._anyListeners=this._anyListeners||[],this._anyListeners.push(t),this}prependAny(t){return this._anyListeners=this._anyListeners||[],this._anyListeners.unshift(t),this}offAny(t){if(!this._anyListeners)return this;if(t){const e=this._anyListeners;for(let s=0;s<e.length;s++)if(t===e[s])return e.splice(s,1),this}else this._anyListeners=[];return this}listenersAny(){return this._anyListeners||[]}onAnyOutgoing(t){return this._anyOutgoingListeners=this._anyOutgoingListeners||[],this._anyOutgoingListeners.push(t),this}prependAnyOutgoing(t){return this._anyOutgoingListeners=this._anyOutgoingListeners||[],this._anyOutgoingListeners.unshift(t),this}offAnyOutgoing(t){if(!this._anyOutgoingListeners)return this;if(t){const e=this._anyOutgoingListeners;for(let s=0;s<e.length;s++)if(t===e[s])return e.splice(s,1),this}else this._anyOutgoingListeners=[];return this}listenersAnyOutgoing(){return this._anyOutgoingListeners||[]}notifyOutgoingListeners(t){if(this._anyOutgoingListeners&&this._anyOutgoingListeners.length){const e=this._anyOutgoingListeners.slice();for(const s of e)s.apply(this,t.data)}}}function wt(t){t=t||{},this.ms=t.min||100,this.max=t.max||1e4,this.factor=t.factor||2,this.jitter=t.jitter>0&&t.jitter<=1?t.jitter:0,this.attempts=0}wt.prototype.duration=function(){var t=this.ms*Math.pow(this.factor,this.attempts++);if(this.jitter){var e=Math.random(),s=Math.floor(e*this.jitter*t);t=1&Math.floor(10*e)?t+s:t-s}return 0|Math.min(t,this.max)},wt.prototype.reset=function(){this.attempts=0},wt.prototype.setMin=function(t){this.ms=t},wt.prototype.setMax=function(t){this.max=t},wt.prototype.setJitter=function(t){this.jitter=t};class kt extends E{constructor(t,s){var n;super(),this.nsps={},this.subs=[],t&&"object"==typeof t&&(s=t,t=void 0),(s=s||{}).path=s.path||"/socket.io",this.opts=s,S(this,s),this.reconnection(!1!==s.reconnection),this.reconnectionAttempts(s.reconnectionAttempts||1/0),this.reconnectionDelay(s.reconnectionDelay||1e3),this.reconnectionDelayMax(s.reconnectionDelayMax||5e3),this.randomizationFactor(null!==(n=s.randomizationFactor)&&void 0!==n?n:.5),this.backoff=new wt({min:this.reconnectionDelay(),max:this.reconnectionDelayMax(),jitter:this.randomizationFactor()}),this.timeout(null==s.timeout?2e4:s.timeout),this._readyState="closed",this.uri=t;const i=s.parser||e;this.encoder=new i.Encoder,this.decoder=new i.Decoder,this._autoConnect=!1!==s.autoConnect,this._autoConnect&&this.open()}reconnection(t){return arguments.length?(this._reconnection=!!t,t||(this.skipReconnect=!0),this):this._reconnection}reconnectionAttempts(t){return void 0===t?this._reconnectionAttempts:(this._reconnectionAttempts=t,this)}reconnectionDelay(t){var e;return void 0===t?this._reconnectionDelay:(this._reconnectionDelay=t,null===(e=this.backoff)||void 0===e||e.setMin(t),this)}randomizationFactor(t){var e;return void 0===t?this._randomizationFactor:(this._randomizationFactor=t,null===(e=this.backoff)||void 0===e||e.setJitter(t),this)}reconnectionDelayMax(t){var e;return void 0===t?this._reconnectionDelayMax:(this._reconnectionDelayMax=t,null===(e=this.backoff)||void 0===e||e.setMax(t),this)}timeout(t){return arguments.length?(this._timeout=t,this):this._timeout}maybeReconnectOnOpen(){!this._reconnecting&&this._reconnection&&0===this.backoff.attempts&&this.reconnect()}open(t){if(~this._readyState.indexOf("open"))return this;this.engine=new tt(this.uri,this.opts);const e=this.engine,s=this;this._readyState="opening",this.skipReconnect=!1;const n=_t(e,"open",function(){s.onopen(),t&&t()}),i=e=>{this.cleanup(),this._readyState="closed",this.emitReserved("error",e),t?t(e):this.maybeReconnectOnOpen()},r=_t(e,"error",i);if(!1!==this._timeout){const t=this._timeout,s=this.setTimeoutFn(()=>{n(),i(new Error("timeout")),e.close()},t);this.opts.autoUnref&&s.unref(),this.subs.push(()=>{this.clearTimeoutFn(s)})}return this.subs.push(n),this.subs.push(r),this}connect(t){return this.open(t)}onopen(){this.cleanup(),this._readyState="open",this.emitReserved("open");const t=this.engine;this.subs.push(_t(t,"ping",this.onping.bind(this)),_t(t,"data",this.ondata.bind(this)),_t(t,"error",this.onerror.bind(this)),_t(t,"close",this.onclose.bind(this)),_t(this.decoder,"decoded",this.ondecoded.bind(this)))}onping(){this.emitReserved("ping")}ondata(t){try{this.decoder.add(t)}catch(t){this.onclose("parse error",t)}}ondecoded(t){C(()=>{this.emitReserved("packet",t)},this.setTimeoutFn)}onerror(t){this.emitReserved("error",t)}socket(t,e){let s=this.nsps[t];return s?this._autoConnect&&!s.active&&s.connect():(s=new vt(this,t,e),this.nsps[t]=s),s}_destroy(t){const e=Object.keys(this.nsps);for(const t of e)if(this.nsps[t].active)return;this._close()}_packet(t){const e=this.encoder.encode(t);for(let s=0;s<e.length;s++)this.engine.write(e[s],t.options)}cleanup(){this.subs.forEach(t=>t()),this.subs.length=0,this.decoder.destroy()}_close(){this.skipReconnect=!0,this._reconnecting=!1,this.onclose("forced close")}disconnect(){return this._close()}onclose(t,e){var s;this.cleanup(),null===(s=this.engine)||void 0===s||s.close(),this.backoff.reset(),this._readyState="closed",this.emitReserved("close",t,e),this._reconnection&&!this.skipReconnect&&this.reconnect()}reconnect(){if(this._reconnecting||this.skipReconnect)return this;const t=this;if(this.backoff.attempts>=this._reconnectionAttempts)this.backoff.reset(),this.emitReserved("reconnect_failed"),this._reconnecting=!1;else{const e=this.backoff.duration();this._reconnecting=!0;const s=this.setTimeoutFn(()=>{t.skipReconnect||(this.emitReserved("reconnect_attempt",t.backoff.attempts),t.skipReconnect||t.open(e=>{e?(t._reconnecting=!1,t.reconnect(),this.emitReserved("reconnect_error",e)):t.onreconnect()}))},e);this.opts.autoUnref&&s.unref(),this.subs.push(()=>{this.clearTimeoutFn(s)})}}onreconnect(){const t=this.backoff.attempts;this._reconnecting=!1,this.backoff.reset(),this.emitReserved("reconnect",t)}}const Et={};function Ct(t,e){"object"==typeof t&&(e=t,t=void 0);const s=function(t,e="",s){let n=t;s=s||"undefined"!=typeof location&&location,null==t&&(t=s.protocol+"//"+s.host),"string"==typeof t&&("/"===t.charAt(0)&&(t="/"===t.charAt(1)?s.protocol+t:s.host+t),/^(https?|wss?):\/\//.test(t)||(t=void 0!==s?s.protocol+"//"+t:"https://"+t),n=J(t)),n.port||(/^(http|ws)$/.test(n.protocol)?n.port="80":/^(http|ws)s$/.test(n.protocol)&&(n.port="443")),n.path=n.path||"/";const i=-1!==n.host.indexOf(":")?"["+n.host+"]":n.host;return n.id=n.protocol+"://"+i+":"+n.port+e,n.href=n.protocol+"://"+i+(s&&s.port===n.port?"":":"+n.port),n}(t,(e=e||{}).path||"/socket.io"),n=s.source,i=s.id,r=s.path,o=Et[i]&&r in Et[i].nsps;let a;return e.forceNew||e["force new connection"]||!1===e.multiplex||o?a=new kt(n,e):(Et[i]||(Et[i]=new kt(n,e)),a=Et[i]),s.query&&!e.query&&(e.query=s.queryKey),a.socket(s.path,e)}Object.assign(Ct,{Manager:kt,Socket:vt,io:Ct,connect:Ct});var Tt=function(t,e,s,n){return new(s||(s=Promise))(function(i,r){function o(t){try{c(n.next(t))}catch(t){r(t)}}function a(t){try{c(n.throw(t))}catch(t){r(t)}}function c(t){t.done?i(t.value):function(t){return t instanceof s?t:new s(function(e){e(t)})}(t.value).then(o,a)}c((n=n.apply(t,e||[])).next())})};class At extends EventTarget{constructor(){super(...arguments),this.peerConnections={}}init(){return Tt(this,void 0,void 0,function*(){return this.socket=Ct("http://localhost:3030"),new Promise((t,e)=>{this.socket.once("connect",()=>{var e;this._userId=this.socket.id,e=this.socket.id,Rt=e,this.setupSocketListeners(),t()}),this.socket.once("connect_error",e),this.socket.once("error",e)})})}get userId(){if(!this._userId)throw new Error("User not connected yet");return this._userId}publish(t){this.publishStream=t}register(t){if(!this.publishStream)throw new Error("Call publish() before register()");this._confId=t,this.sendMessage({from:this.userId,payload:{action:"join"}}),console.log(`[CONF] Join request sent for room ${t}`)}unregister(){Object.values(this.peerConnections).forEach(t=>t.close()),this.peerConnections={},this._confId=void 0,this.socket.disconnect(),console.log("[CONF] Unregistered and socket closed")}setupSocketListeners(){this.socket.on("message",t=>Tt(this,void 0,void 0,function*(){if(!this._confId)return;const{from:e,payload:s}=t;switch(s.action){case"join":console.log(`[RTC] Join received from ${e}`),yield this.createPeerConnection(e,!0);break;case"offer":console.log(`[RTC] Offer received from ${e}`),yield this.handleOffer(e,s.sdp);break;case"answer":console.log(`[RTC] Answer received from ${e}`),yield this.handleAnswer(e,s.sdp);break;case"ice":console.log(`[RTC] ICE received from ${e}`),yield this.handleIce(e,s.candidate);break;case"close":console.log(`[RTC] Peer ${s.disconnect} disconnected`),this.removePeer(s.disconnect),this.dispatchEvent(new CustomEvent("peopleLeave",{detail:{leaveId:s.disconnect}})),console.log("[Socket] leave"+s.disconnect)}}))}createPeerConnection(t,e){return Tt(this,void 0,void 0,function*(){var s;if(this.peerConnections[t])return;const i=new RTCPeerConnection;if(this.peerConnections[t]=i,null===(s=this.publishStream)||void 0===s||s.mediastream.getTracks().forEach(t=>{i.addTrack(t,this.publishStream.mediastream)}),i.ontrack=e=>{console.log("[RTC] Track received"),this.dispatchEvent(new CustomEvent("stream",{detail:{stream:new n(e.streams[0],t)}}))},i.onicecandidate=e=>{e.candidate&&this.sendMessage({from:this.userId,target:t,payload:{action:"ice",candidate:e.candidate}})},e){const e=yield i.createOffer();yield i.setLocalDescription(e),this.sendMessage({from:this.userId,target:t,payload:{action:"offer",sdp:e}})}})}handleOffer(t,e){return Tt(this,void 0,void 0,function*(){yield this.createPeerConnection(t,!1);const s=this.peerConnections[t];yield s.setRemoteDescription(new RTCSessionDescription(e));const n=yield s.createAnswer();yield s.setLocalDescription(n),this.sendMessage({from:this.userId,target:t,payload:{action:"answer",sdp:n}}),this.dispatchEvent(new CustomEvent("newPeople"))})}handleAnswer(t,e){return Tt(this,void 0,void 0,function*(){const s=this.peerConnections[t];s&&(yield s.setRemoteDescription(new RTCSessionDescription(e)),this.dispatchEvent(new CustomEvent("newPeople")))})}handleIce(t,e){return Tt(this,void 0,void 0,function*(){const s=this.peerConnections[t];s&&(yield s.addIceCandidate(e))})}removePeer(t){var e;null===(e=this.peerConnections[t])||void 0===e||e.close(),delete this.peerConnections[t]}sendMessage(t){this.socket.emit("message",t)}}const Ot=new At;Ot.init();let Rt=null;class St extends EventTarget{constructor(t){super(),this.name=t,this.id=2,this.knownStreams=[],this.setupListener()}setupListener(){Ot.addEventListener("stream",t=>{this.newStream(t)}),Ot.addEventListener("peopleLeave",t=>{this.peopleLeave(t)})}publish(t){Ot.publish(t)}join(){Ot.register(this.id)}leave(){Ot.unregister()}getMembers(){}newStream(t){if(this.knownStreams.includes(t.detail.stream))return;this.knownStreams.push(t.detail.stream);const e=new CustomEvent("newstream",{detail:{stream:t.detail.stream}});this.dispatchEvent(e)}peopleLeave(t){const e=new CustomEvent("peopleLeave",{detail:{leaveId:t.detail.leaveId}});console.log("[Conf] leave"+t.detail.leaveId),this.dispatchEvent(e)}}export{St as Conference,s as HelloWorld,n as Stream};
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SocketInteraction } from "./core/SocketInteraction";
|
|
2
|
+
declare const socketInteraction: SocketInteraction;
|
|
3
|
+
declare function uidGenerator(): String;
|
|
4
|
+
declare function setUserId(newId: string): void;
|
|
5
|
+
declare function getId(): string | undefined;
|
|
6
|
+
export { setUserId };
|
|
7
|
+
export { getId };
|
|
8
|
+
export { socketInteraction };
|
|
9
|
+
export { uidGenerator };
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mitmi",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "webpack"
|
|
9
|
+
},
|
|
10
|
+
"description": "exemple",
|
|
11
|
+
"keywords": [],
|
|
12
|
+
"author": "",
|
|
13
|
+
"license": "ISC",
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"ts-loader": "^9.5.4",
|
|
16
|
+
"typescript": "^5.9.3",
|
|
17
|
+
"webpack": "^5.103.0",
|
|
18
|
+
"webpack-cli": "^6.0.1",
|
|
19
|
+
"socket.io": "^4.8.1",
|
|
20
|
+
"socket.io-client": "^4.8.1"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Stream } from "./Stream";
|
|
2
|
+
import { socketInteraction } from "./utils";
|
|
3
|
+
|
|
4
|
+
class Conference extends EventTarget {
|
|
5
|
+
name: string;
|
|
6
|
+
id: number;
|
|
7
|
+
knownStreams: Array<Stream | void>;
|
|
8
|
+
constructor(name: string) {
|
|
9
|
+
super();
|
|
10
|
+
this.name = name;
|
|
11
|
+
this.id = 2; //TODO change later for a random
|
|
12
|
+
this.knownStreams = [];
|
|
13
|
+
this.setupListener();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
private setupListener() {
|
|
17
|
+
socketInteraction.addEventListener("stream", (e) => {
|
|
18
|
+
this.newStream(e);
|
|
19
|
+
});
|
|
20
|
+
socketInteraction.addEventListener("peopleLeave", (e) => {
|
|
21
|
+
this.peopleLeave(e);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
publish(stream: Stream) {
|
|
26
|
+
socketInteraction.publish(stream);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
join() {
|
|
30
|
+
socketInteraction.register(this.id);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
leave() {
|
|
34
|
+
socketInteraction.unregister();
|
|
35
|
+
}
|
|
36
|
+
getMembers() {}
|
|
37
|
+
|
|
38
|
+
private newStream(e: any) {
|
|
39
|
+
if (this.knownStreams.includes(e.detail.stream)) return;
|
|
40
|
+
this.knownStreams.push(e.detail.stream);
|
|
41
|
+
const newevent = new CustomEvent("newstream", {
|
|
42
|
+
detail: {
|
|
43
|
+
stream: e.detail.stream,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
this.dispatchEvent(newevent);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private peopleLeave(e: any) {
|
|
50
|
+
const newevent = new CustomEvent("peopleLeave", {
|
|
51
|
+
detail: {
|
|
52
|
+
leaveId: e.detail.leaveId,
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
console.log("[Conf] leave" + e.detail.leaveId);
|
|
56
|
+
this.dispatchEvent(newevent);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export { Conference };
|
package/src/Stream.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { uidGenerator, getId } from "./utils";
|
|
2
|
+
|
|
3
|
+
class Stream {
|
|
4
|
+
mediastream: MediaStream;
|
|
5
|
+
domElement: undefined | HTMLVideoElement;
|
|
6
|
+
owner: string;
|
|
7
|
+
id: String;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* @param mediastream
|
|
12
|
+
* @param owner "" => ourself, id instead
|
|
13
|
+
*/
|
|
14
|
+
constructor(mediastream: MediaStream, owner: string) {
|
|
15
|
+
this.mediastream = mediastream;
|
|
16
|
+
this.owner = owner;
|
|
17
|
+
this.id = owner + "_usermedia";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static async getCamera(video: boolean, audio: boolean): Promise<Stream> {
|
|
21
|
+
let mediastream = await navigator.mediaDevices.getUserMedia({
|
|
22
|
+
video: video,
|
|
23
|
+
audio: audio,
|
|
24
|
+
});
|
|
25
|
+
let newStream = new Stream(mediastream, "");
|
|
26
|
+
return newStream;
|
|
27
|
+
}
|
|
28
|
+
static getScreen() {}
|
|
29
|
+
|
|
30
|
+
attachToElement(domElement: HTMLVideoElement): void {
|
|
31
|
+
this.domElement = domElement;
|
|
32
|
+
domElement.srcObject = this.mediastream;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
detachToElement(): void {
|
|
36
|
+
if (!this.domElement) return;
|
|
37
|
+
this.domElement.srcObject = null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
muteAudio(): void {
|
|
41
|
+
this.mediastream.getAudioTracks()[0].enabled = false;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
unmuteAudio(): void {
|
|
45
|
+
this.mediastream.getAudioTracks()[0].enabled = true;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export { Stream };
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const localServerUrl = "http://localhost:3030";
|
|
2
|
+
export const serverUrl = "https://signaling.savinienbarbotaud.fr";
|
|
3
|
+
|
|
4
|
+
export const stunServers = {
|
|
5
|
+
iceServers: [
|
|
6
|
+
{
|
|
7
|
+
urls: [
|
|
8
|
+
"stun:stun.l.google.com:19302",
|
|
9
|
+
"stun:stun2.l.google.com:19302",
|
|
10
|
+
"stun:stun4.l.google.com:19302",
|
|
11
|
+
],
|
|
12
|
+
},
|
|
13
|
+
],
|
|
14
|
+
};
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { io, Socket } from "socket.io-client";
|
|
2
|
+
import { localServerUrl, serverUrl } from "../constants";
|
|
3
|
+
import { setUserId } from "../utils";
|
|
4
|
+
import { Stream } from "../Stream";
|
|
5
|
+
|
|
6
|
+
interface SocketMessage {
|
|
7
|
+
from: string;
|
|
8
|
+
target?: string;
|
|
9
|
+
payload: {
|
|
10
|
+
action: "join" | "offer" | "answer" | "ice" | "close";
|
|
11
|
+
sdp?: RTCSessionDescriptionInit;
|
|
12
|
+
candidate?: RTCIceCandidate;
|
|
13
|
+
message?: string;
|
|
14
|
+
disconnect?: string;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class SocketInteraction extends EventTarget {
|
|
19
|
+
private socket!: Socket;
|
|
20
|
+
private _userId?: string;
|
|
21
|
+
private _confId?: number;
|
|
22
|
+
private publishStream?: Stream;
|
|
23
|
+
|
|
24
|
+
private peerConnections: Record<string, RTCPeerConnection> = {};
|
|
25
|
+
|
|
26
|
+
async init(): Promise<void> {
|
|
27
|
+
this.socket = io(serverUrl);
|
|
28
|
+
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
this.socket.once("connect", () => {
|
|
31
|
+
this._userId = this.socket.id;
|
|
32
|
+
setUserId(this.socket.id!);
|
|
33
|
+
this.setupSocketListeners();
|
|
34
|
+
resolve();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
this.socket.once("connect_error", reject);
|
|
38
|
+
this.socket.once("error", reject);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
get userId(): string {
|
|
43
|
+
if (!this._userId) throw new Error("User not connected yet");
|
|
44
|
+
return this._userId;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
publish(stream: Stream) {
|
|
48
|
+
this.publishStream = stream;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
register(confId: number) {
|
|
52
|
+
if (!this.publishStream) {
|
|
53
|
+
throw new Error("Call publish() before register()");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
this._confId = confId;
|
|
57
|
+
|
|
58
|
+
this.sendMessage({
|
|
59
|
+
from: this.userId,
|
|
60
|
+
payload: { action: "join" },
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
console.log(`[CONF] Join request sent for room ${confId}`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
unregister() {
|
|
67
|
+
Object.values(this.peerConnections).forEach((pc) => pc.close());
|
|
68
|
+
this.peerConnections = {};
|
|
69
|
+
|
|
70
|
+
this._confId = undefined;
|
|
71
|
+
this.socket.disconnect();
|
|
72
|
+
|
|
73
|
+
console.log("[CONF] Unregistered and socket closed");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private setupSocketListeners() {
|
|
77
|
+
this.socket.on("message", async (message: SocketMessage) => {
|
|
78
|
+
if (!this._confId) return;
|
|
79
|
+
|
|
80
|
+
const { from, payload } = message;
|
|
81
|
+
|
|
82
|
+
switch (payload.action) {
|
|
83
|
+
case "join":
|
|
84
|
+
console.log(`[RTC] Join received from ${from}`);
|
|
85
|
+
await this.createPeerConnection(from, true);
|
|
86
|
+
break;
|
|
87
|
+
|
|
88
|
+
case "offer":
|
|
89
|
+
console.log(`[RTC] Offer received from ${from}`);
|
|
90
|
+
await this.handleOffer(from, payload.sdp!);
|
|
91
|
+
break;
|
|
92
|
+
|
|
93
|
+
case "answer":
|
|
94
|
+
console.log(`[RTC] Answer received from ${from}`);
|
|
95
|
+
await this.handleAnswer(from, payload.sdp!);
|
|
96
|
+
break;
|
|
97
|
+
|
|
98
|
+
case "ice":
|
|
99
|
+
console.log(`[RTC] ICE received from ${from}`);
|
|
100
|
+
await this.handleIce(from, payload.candidate!);
|
|
101
|
+
break;
|
|
102
|
+
|
|
103
|
+
case "close":
|
|
104
|
+
console.log(`[RTC] Peer ${payload.disconnect} disconnected`);
|
|
105
|
+
this.removePeer(payload.disconnect!);
|
|
106
|
+
this.dispatchEvent(
|
|
107
|
+
new CustomEvent("peopleLeave", {
|
|
108
|
+
detail: { leaveId: payload.disconnect },
|
|
109
|
+
})
|
|
110
|
+
);
|
|
111
|
+
console.log("[Socket] leave" + payload.disconnect);
|
|
112
|
+
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private async createPeerConnection(remoteUserId: string, initiator: boolean) {
|
|
119
|
+
if (this.peerConnections[remoteUserId]) return; //existe deja
|
|
120
|
+
|
|
121
|
+
const pc = new RTCPeerConnection();
|
|
122
|
+
this.peerConnections[remoteUserId] = pc;
|
|
123
|
+
|
|
124
|
+
// add local tracks
|
|
125
|
+
this.publishStream?.mediastream.getTracks().forEach((track) => {
|
|
126
|
+
pc.addTrack(track, this.publishStream!.mediastream);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
pc.ontrack = (event) => {
|
|
130
|
+
console.log("[RTC] Track received");
|
|
131
|
+
this.dispatchEvent(
|
|
132
|
+
new CustomEvent("stream", {
|
|
133
|
+
detail: { stream: new Stream(event.streams[0], remoteUserId) },
|
|
134
|
+
})
|
|
135
|
+
);
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
pc.onicecandidate = (event) => {
|
|
139
|
+
if (event.candidate) {
|
|
140
|
+
this.sendMessage({
|
|
141
|
+
from: this.userId,
|
|
142
|
+
target: remoteUserId,
|
|
143
|
+
payload: { action: "ice", candidate: event.candidate },
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
if (initiator) {
|
|
149
|
+
const offer = await pc.createOffer();
|
|
150
|
+
await pc.setLocalDescription(offer);
|
|
151
|
+
|
|
152
|
+
this.sendMessage({
|
|
153
|
+
from: this.userId,
|
|
154
|
+
target: remoteUserId,
|
|
155
|
+
payload: { action: "offer", sdp: offer },
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private async handleOffer(from: string, sdp: RTCSessionDescriptionInit) {
|
|
161
|
+
await this.createPeerConnection(from, false);
|
|
162
|
+
|
|
163
|
+
const pc = this.peerConnections[from];
|
|
164
|
+
await pc.setRemoteDescription(new RTCSessionDescription(sdp));
|
|
165
|
+
|
|
166
|
+
const answer = await pc.createAnswer();
|
|
167
|
+
await pc.setLocalDescription(answer);
|
|
168
|
+
|
|
169
|
+
this.sendMessage({
|
|
170
|
+
from: this.userId,
|
|
171
|
+
target: from,
|
|
172
|
+
payload: { action: "answer", sdp: answer },
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
this.dispatchEvent(new CustomEvent("newPeople"));
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
private async handleAnswer(from: string, sdp: RTCSessionDescriptionInit) {
|
|
179
|
+
const pc = this.peerConnections[from];
|
|
180
|
+
if (!pc) return;
|
|
181
|
+
|
|
182
|
+
await pc.setRemoteDescription(new RTCSessionDescription(sdp));
|
|
183
|
+
this.dispatchEvent(new CustomEvent("newPeople"));
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private async handleIce(from: string, candidate: RTCIceCandidate) {
|
|
187
|
+
const pc = this.peerConnections[from];
|
|
188
|
+
if (!pc) return;
|
|
189
|
+
|
|
190
|
+
await pc.addIceCandidate(candidate);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
private removePeer(remoteId: string) {
|
|
194
|
+
this.peerConnections[remoteId]?.close();
|
|
195
|
+
delete this.peerConnections[remoteId];
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private sendMessage(msg: SocketMessage) {
|
|
199
|
+
this.socket.emit("message", msg);
|
|
200
|
+
}
|
|
201
|
+
}
|
package/src/index.ts
ADDED
package/src/utils.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { SocketInteraction } from "./core/SocketInteraction";
|
|
2
|
+
|
|
3
|
+
const socketInteraction = new SocketInteraction();
|
|
4
|
+
socketInteraction.init();
|
|
5
|
+
|
|
6
|
+
function uidGenerator(): String {
|
|
7
|
+
var S4 = function () {
|
|
8
|
+
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
|
|
9
|
+
};
|
|
10
|
+
return (
|
|
11
|
+
S4() +
|
|
12
|
+
S4() +
|
|
13
|
+
"-" +
|
|
14
|
+
S4() +
|
|
15
|
+
"-" +
|
|
16
|
+
S4() +
|
|
17
|
+
"-" +
|
|
18
|
+
S4() +
|
|
19
|
+
"-" +
|
|
20
|
+
S4() +
|
|
21
|
+
S4() +
|
|
22
|
+
S4()
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let userId: undefined | string = undefined;
|
|
27
|
+
function setUserId(newId: string) {
|
|
28
|
+
userId = newId;
|
|
29
|
+
}
|
|
30
|
+
function getId() {
|
|
31
|
+
return userId;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export { setUserId };
|
|
35
|
+
export { getId };
|
|
36
|
+
export { socketInteraction };
|
|
37
|
+
export { uidGenerator };
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
mode: "production",
|
|
5
|
+
entry: "./src/index.ts",
|
|
6
|
+
module: {
|
|
7
|
+
rules: [
|
|
8
|
+
{
|
|
9
|
+
test: /\.ts$/,
|
|
10
|
+
use: "ts-loader",
|
|
11
|
+
exclude: /node_modules/,
|
|
12
|
+
},
|
|
13
|
+
],
|
|
14
|
+
},
|
|
15
|
+
resolve: {
|
|
16
|
+
extensions: [".ts", ".js"],
|
|
17
|
+
},
|
|
18
|
+
output: {
|
|
19
|
+
filename: "index.js",
|
|
20
|
+
path: path.resolve(__dirname, "dist"),
|
|
21
|
+
library: {
|
|
22
|
+
type: "module",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
experiments: {
|
|
26
|
+
outputModule: true,
|
|
27
|
+
},
|
|
28
|
+
};
|