librecast-live
Version:
Live Streaming Video Platform with IPv6 Multicast
2 lines (1 loc) • 8.55 kB
JavaScript
"use strict";const LIBRECAST=function(){function t(t){this.code=t,this.name=e.ErrorMsg[t],this.errormsg="ERROR ("+this.code+") "+this.name}const e={DEFAULT_TIMEOUT:5e3,NO_TIMEOUT:-1,WS_CONNECTING:0,WS_OPEN:1,WS_CLOSING:2,WS_CLOSED:3,OP_NOOP:1,OP_SETOPT:2,OP_SOCKET_NEW:3,OP_SOCKET_GETOPT:4,OP_SOCKET_SETOPT:5,OP_SOCKET_LISTEN:6,OP_SOCKET_IGNORE:7,OP_SOCKET_CLOSE:8,OP_SOCKET_MSG:9,OP_CHANNEL_NEW:10,OP_CHANNEL_GETMSG:11,OP_CHANNEL_GETOPT:12,OP_CHANNEL_SETOPT:13,OP_CHANNEL_GETVAL:14,OP_CHANNEL_SETVAL:15,OP_CHANNEL_BIND:16,OP_CHANNEL_UNBIND:17,OP_CHANNEL_JOIN:18,OP_CHANNEL_PART:19,OP_CHANNEL_SEND:20,HEADER_LENGTH:25,ERR_SUCCESS:0,ERR_FAILURE:1,ERR_WEBSOCKET_UNSUPPORTED:2,ERR_WEBSOCKET_NOTREADY:3,ERR_CALLBACK_NOT_FUNCTION:4,ERR_MISSING_ARG:5,ErrorMsg:{}};e.ErrorMsg[e.ERR_SUCCESS]="Success",e.ErrorMsg[e.ERR_FAILURE]="Failure",e.ErrorMsg[e.ERR_WEBSOCKET_UNSUPPORTED]="Browser does not support websockets",e.ErrorMsg[e.ERR_WEBSOCKET_NOTREADY]="Websocket not ready",e.ErrorMsg[e.ERR_CALLBACK_NOT_FUNCTION]="Callback not a function",e.ErrorMsg[e.ERR_MISSING_ARGUMENT]="Required argument is missing";const o=function(t,e,o,s){let n,i;for(i=0;i<o;i++)n=e.charCodeAt(i),n<=127?s.setUint8(t++,n):n<=2047?(s.setUint8(t++,192|n>>>6),s.setUint8(t++,128|63&n)):n<=65535?(s.setUint8(t++,224|n>>>12),s.setUint8(t++,128|n>>>6&63),s.setUint8(t++,128|63&n)):console.log("UTF-16 surrogate pair, ignoring");return t},s=function(t){const e=new ArrayBuffer(4),o=new DataView(e,0);let s=1;o.setUint32(0,t,!0);for(let t=0,e=o.getUint32(0,!0);e>127;e>>>=7)o.setUint8(t++,128|e),s++;return s},n=function(t,e,s){let n=s;const i=new ArrayBuffer(e),c=new Uint8Array(i),r=new DataView(i);for(let e=0;e<t.length;e++)if(null!==t[e]){let s;const i=t[e].length;for(r.setUint8(n,i),s=r.getUint8(n);s>127;s>>>=7)r.setUint8(n++,128|s);r.setUint8(n++,s),"object"==typeof t[e]?(c.set(new Uint8Array(t[e]),n),n+=i):n=o(n,t[e],i,r)}return i},i=function(t,e){const o=t.length,i=function(t){let e=0;for(let o=0;o<t.length;o++)null!==t[o]&&(e+=s(t[o].length)+t[o].length);return e}(e)+o,c=n(e,i,o);return new Uint8Array(c).set(t),c},c=function(t,e){void 0===e&&(e=0);const o=[],s=new DataView(t),n=t.byteLength;for(let i=e,c=0;i<n;i+=c){let e,r=0,l=0;do{if(i>=n)throw new Error("overflow");e=s.getUint8(i++),r|=(127&e)<<l,l+=7}while(128&e);if(c=r,i+c>n)break;o.push(new Uint8Array(t.slice(i,i+c)))}return o},r={bytes7BitLength:s,convertUTF16toUTF8:o,encode7BitLength:function(t){const e=s(t);let o,n=0;const i=new ArrayBuffer(e),c=new DataView(i);for(c.setUint8(n,t,!0),o=c.getUint8(n);o>127;o>>>=7)c.setUint8(n++,128|o);return c.setUint8(n++,o),i},keysEqual:function(t,e){const o=t.byteLength;if(o!==e.byteLength)return!1;for(let s=0;s<o;s++)if(t[s]!==e[s])return!1;return!0},wirePack:function(t,e,o){return i([t,e],o)},wirePackPre:i,wirePack7Bit:n,wireUnpack:function(t){const e=new DataView(t);return[e.getUint8(0),e.getUint8(1),c(t,2)]},wireUnpack7Bit:c};return e.Context=class{constructor(){console.log("Librecast context constructor"),this.url="https:"===location.protocol?"wss://":"ws://",this.url+=document.location.host+"/",this.callstack=[],this.onconnect=new Promise((t=>{this.resolveconnect=t})),this.connect()}connect(){if(console.log("Librecast.connect()"),!window.WebSocket)throw console.log("websockets unsupported"),new t(e.ERR_WEBSOCKET_UNSUPPORTED);console.log("websockets supported"),this.websocket=new WebSocket(this.url,"librecast"),this.websocket.binaryType="arraybuffer",this.websocket.onclose=t=>{this.wsClose(t)},this.websocket.onerror=t=>{this.wsError(t)},this.websocket.onmessage=t=>{this.wsMessage(t)},this.websocket.onopen=t=>{this.wsOpen(t)}}close(){console.log("Librecast close()"),this.websocket.close()}get token(){return Math.floor(4294967295*Math.random())}callback(t,o,s,n){const i=this.token,c={};return c.resolve=t,c.reject=o,c.created=Date.now(),c.repeat=n,this.callstack[i]=c,console.log("callback created with token = "+i),s!==e.NO_TIMEOUT&&(void 0===s&&(s=e.DEFAULT_TIMEOUT),console.log("setting callback timer "+i),c.timeout=setTimeout((()=>{o("callback ("+i+") timeout"),delete this.callstack[i]}),s)),i}cancelCallback(t){console.log("cancelling callback token "+t),void 0!==this.callstack[t]&&void 0!==this.callstack[t].timeout&&clearTimeout(this.callstack[t].timeout),delete this.callstack[t]}send(t){let o,s,n;if(o=new ArrayBuffer(e.HEADER_LENGTH+4*t.len),s=new DataView(o),void 0!==t.data&&t.len>0)if("object"==typeof t.data){n=e.HEADER_LENGTH+t.len;const i=new Uint8Array(n);i.set(new Uint8Array(t.data),e.HEADER_LENGTH),o=i.buffer,s=new DataView(o)}else n=r.convertUTF16toUTF8(e.HEADER_LENGTH,t.data,t.len,s);s.setUint8(0,t.opcode),s.setUint32(1,n-e.HEADER_LENGTH),s.setUint32(5,t.id),s.setUint32(9,t.id2),s.setUint32(13,t.token),this.websocket.send(o)}wsClose(t){console.log("websocket close: ("+t.code+") "+t.reason),console.log("websocket.readyState: "+this.websocket.readyState),console.log("reinitializing websocket"),this.connect()}wsError(t){console.log("websocket error"+t.message),console.log("websocket.readyState: "+this.websocket.readyState)}wsMessage(t){if(console.log("websocket message received (type="+t.type+")"),"object"==typeof t&&t.data instanceof ArrayBuffer){const o=new DataView(t.data),s=new e.Message(t.data);s.opcode=o.getUint8(0),s.len=o.getUint32(1),s.id=o.getUint32(5),s.id2=o.getUint32(9),s.token=o.getUint32(13),s.payload=t.data.slice(e.HEADER_LENGTH),console.log("opcode: "+s.opcode),console.log("len: "+s.len),console.log("id: "+s.id),console.log("id2: "+s.id2),console.log("token: "+s.token),void 0!==this.callstack[s.token]&&(this.callstack[s.token].updated=Date.now(),s.sent=this.callstack[s.token].created,s.recv=this.callstack[s.token].updated,s.delay=s.recv-s.sent,console.log("message reponse took "+s.delay+" ms"),void 0!==this.callstack[s.token].timeout&&(console.log("clearing callback timer "+s.token),clearTimeout(this.callstack[s.token].timeout),this.callstack[s.token].timeout=void 0),void 0!==this.callstack[s.token].resolve&&(this.callstack[s.token].resolve(s),void 0!==this.callstack[s.token]&&(this.callstack[s.token].repeat||this.cancelCallback(s.token))))}}wsOpen(t){console.log("websocket open"),console.log("websocket.readyState: "+this.websocket.readyState),this.resolveconnect()}},e.Socket=class{constructor(t){if(console.log("Socket constructor"),void 0===t)throw new Error("Librecast.Context required");this.lctx=t,this.id=void 0,this.oncreate=new Promise(((t,o)=>{const s=new e.Message;s.opcode=e.OP_SOCKET_NEW,s.token=this.lctx.callback(t,o),this.lctx.send(s)})).then((t=>{this.id=t.id}))}op(o,s,n,i){return new Promise(((c,r)=>{if(this.lctx.websocket.readyState===e.WS_OPEN){const t=new e.Message(s);t.opcode=o,t.id=this.id,!1!==i&&(t.token=this.lctx.callback(c,r,n)),this.lctx.send(t)}else r(t(e.ERR_WEBSOCKET_NOTREADY))}))}close(){return this.lctx.cancelCallback(this.token),this.op(e.OP_SOCKET_CLOSE,void 0,void 0,!1)}listen(o,s){if(console.log("listening on socket "+this.id),this.lctx.websocket.readyState===e.WS_OPEN){const t=new e.Message;t.opcode=e.OP_SOCKET_LISTEN,t.id=this.id,t.token=this.lctx.callback(o,s,e.NO_TIMEOUT,!0),this.token=t.token,this.lctx.send(t)}else s(t(e.ERR_WEBSOCKET_NOTREADY))}},e.Channel=class{constructor(o,s){if(console.log("Channel constructor"),void 0===o)throw new Error("Librecast.Context required");this.lctx=o,this.id=void 0,this.id2=void 0,this.name=s,this.oncreate=new Promise(((o,n)=>{const i=new e.Message(s);i.opcode=e.OP_CHANNEL_NEW,0===i.len&&n(t(e.ERR_MISSING_ARG)),i.token=this.lctx.callback(o,n),this.lctx.send(i)})).then((t=>{this.id=t.id}))}op(o,s,n){return new Promise(((i,c)=>{if(this.lctx.websocket.readyState===e.WS_OPEN){const t=new e.Message(s);t.opcode=o,t.id=this.id,t.id2=this.id2,t.token=this.lctx.callback(i,c,n),console.log("opcode = "+o+", token = "+t.token),this.lctx.send(t)}else c(t(e.ERR_WEBSOCKET_NOTREADY))}))}bind(t){return console.log("binding channel "+this.name+"("+this.id+") to socket "+t.id),this.id2=t.id,this.op(e.OP_CHANNEL_BIND)}join(){return console.log('joining channel "'+this.name+'"'),this.op(e.OP_CHANNEL_JOIN)}part(){return console.log('parting channel "'+this.name+'"'),this.op(e.OP_CHANNEL_PART)}send(t){return this.op(e.OP_CHANNEL_SEND,t,e.NO_TIMEOUT)}},e.Message=class{constructor(t){this.opcode=e.OP_NOOP,this.data=t,t instanceof ArrayBuffer?this.len=t.byteLength:this.len=void 0===this.data?0:t.length,this.id=0,this.id2=0,this.token=0}get utf8(){if(void 0!==this.data){return new TextDecoder("utf-8").decode(new Uint8Array(this.data)).slice(e.HEADER_LENGTH)}}},e.util=r,e}();