diff --git a/src/client.ts b/src/client.ts new file mode 100644 index 000000000..bc8170783 --- /dev/null +++ b/src/client.ts @@ -0,0 +1,100 @@ +import Websock from "./websock"; +import * as message from "./message.js"; +import * as rendezvous from "./rendezvous.js"; +import { loadVp9, loadOpus } from "./codec"; + +const URI = "ws://207.148.17.15"; +const PORT = 21118; +const licenceKey = ""; + +loadVp9(); +loadOpus(); + +export default class Client { + _msgs: any[]; + _ws: Websock | undefined; + _interval: any; + _id: string; + + constructor() { + this._msgs = []; + this._id = ''; + this._interval = setInterval(() => { + while (this._msgs.length) { + this._ws?.sendMessage(this._msgs[0]); + this._msgs.splice(0, 1); + } + }, 1); + } + + close() { + clearInterval(this._interval); + this._ws?.close(); + } + + async connect(id: string) { + const ws = new Websock(URI + ":" + PORT); + this._ws = ws; + this._id = id; + await ws.open(); + const connType = rendezvous.ConnType.DEFAULT_CONN; + const natType = rendezvous.NatType.SYMMETRIC; + const punchHoleRequest = rendezvous.PunchHoleRequest.fromJSON({ + id, + licenceKey, + connType, + natType, + }); + ws.sendRendezvous({ punchHoleRequest }); + const msg = ws.parseRendezvous(await ws.next()); + const phr = msg.punchHoleResponse; + const rr = msg.relayResponse; + if (phr) { + if (phr.failure != rendezvous.PunchHoleResponse_Failure.UNKNOWN) { + switch (phr?.failure) { + case rendezvous.PunchHoleResponse_Failure.ID_NOT_EXIST: + break; + } + ws.close(); + } + } else if (rr) { + await this.connectRelay(rr); + } + } + + async connectRelay(rr: rendezvous.RelayResponse) { + const pk = rr.pk; + let uri = rr.relayServer; + if (uri.indexOf(':') > 0) { + const tmp = uri.split(':'); + const port = parseInt(tmp[1]); + uri = tmp[0] + ':' + (port + 2); + } else { + uri += ':' + (PORT + 1); + } + const uuid = rr.uuid; + const ws = new Websock('ws://' + uri); + await ws.open(); + console.log('Connected to relay server') + this._ws = ws; + const requestRelay = rendezvous.RequestRelay.fromJSON({ + licenceKey, + uuid, + }); + ws.sendRendezvous({ requestRelay }); + await this.secure(pk); + } + + async secure(pk: Uint8Array | undefined) { + // + } +} + +async function testDelay() { + const ws = new Websock(URI + ":" + PORT); + await ws.open(); + console.log(ws.latency()); +} + +await testDelay(); +await new Client().connect("124931507"); diff --git a/src/codec.js b/src/codec.js index 6b44321b6..6f1381d96 100644 --- a/src/codec.js +++ b/src/codec.js @@ -2,61 +2,61 @@ // dev: copy decoder files from node/ogv/dist/* to project dir // dist: .... to dist /* - OGVDemuxerOggW: 'ogv-demuxer-ogg-wasm.js', - OGVDemuxerWebMW: 'ogv-demuxer-webm-wasm.js', - OGVDecoderAudioOpusW: 'ogv-decoder-audio-opus-wasm.js', - OGVDecoderAudioVorbisW: 'ogv-decoder-audio-vorbis-wasm.js', - OGVDecoderVideoTheoraW: 'ogv-decoder-video-theora-wasm.js', - OGVDecoderVideoVP8W: 'ogv-decoder-video-vp8-wasm.js', - OGVDecoderVideoVP8MTW: 'ogv-decoder-video-vp8-mt-wasm.js', - OGVDecoderVideoVP9W: 'ogv-decoder-video-vp9-wasm.js', - OGVDecoderVideoVP9SIMDW: 'ogv-decoder-video-vp9-simd-wasm.js', - OGVDecoderVideoVP9MTW: 'ogv-decoder-video-vp9-mt-wasm.js', - OGVDecoderVideoVP9SIMDMTW: 'ogv-decoder-video-vp9-simd-mt-wasm.js', - OGVDecoderVideoAV1W: 'ogv-decoder-video-av1-wasm.js', - OGVDecoderVideoAV1SIMDW: 'ogv-decoder-video-av1-simd-wasm.js', - OGVDecoderVideoAV1MTW: 'ogv-decoder-video-av1-mt-wasm.js', - OGVDecoderVideoAV1SIMDMTW: 'ogv-decoder-video-av1-simd-mt-wasm.js', + OGVDemuxerOggW: 'ogv-demuxer-ogg-wasm.js', + OGVDemuxerWebMW: 'ogv-demuxer-webm-wasm.js', + OGVDecoderAudioOpusW: 'ogv-decoder-audio-opus-wasm.js', + OGVDecoderAudioVorbisW: 'ogv-decoder-audio-vorbis-wasm.js', + OGVDecoderVideoTheoraW: 'ogv-decoder-video-theora-wasm.js', + OGVDecoderVideoVP8W: 'ogv-decoder-video-vp8-wasm.js', + OGVDecoderVideoVP8MTW: 'ogv-decoder-video-vp8-mt-wasm.js', + OGVDecoderVideoVP9W: 'ogv-decoder-video-vp9-wasm.js', + OGVDecoderVideoVP9SIMDW: 'ogv-decoder-video-vp9-simd-wasm.js', + OGVDecoderVideoVP9MTW: 'ogv-decoder-video-vp9-mt-wasm.js', + OGVDecoderVideoVP9SIMDMTW: 'ogv-decoder-video-vp9-simd-mt-wasm.js', + OGVDecoderVideoAV1W: 'ogv-decoder-video-av1-wasm.js', + OGVDecoderVideoAV1SIMDW: 'ogv-decoder-video-av1-simd-wasm.js', + OGVDecoderVideoAV1MTW: 'ogv-decoder-video-av1-mt-wasm.js', + OGVDecoderVideoAV1SIMDMTW: 'ogv-decoder-video-av1-simd-mt-wasm.js', */ export function loadVp9() { - window.OGVLoader.loadClass( - "OGVDecoderVideoVP9W", - (videoCodecClass) => { - videoCodecClass().then((decoder) => { - decoder.init(() => { - onVp9Ready(decoder) - }) - }) - }, - { worker: true } - ); + window.OGVLoader.loadClass( + "OGVDecoderVideoVP9W", + (videoCodecClass) => { + videoCodecClass().then((decoder) => { + decoder.init(() => { + onVp9Ready(decoder) + }) + }) + }, + { worker: true } + ); } export function loadOpus() { - window.OGVLoader.loadClass( - "OGVDecoderAudioOpusW", - (audioCodecClass) => { - audioCodecClass().then((decoder) => { - decoder.init(() => { - onOpusReady(decoder) - }) - }) - }, - { worker: true } - ); + window.OGVLoader.loadClass( + "OGVDecoderAudioOpusW", + (audioCodecClass) => { + audioCodecClass().then((decoder) => { + decoder.init(() => { + onOpusReady(decoder) + }) + }) + }, + { worker: true } + ); } async function onVp9Ready(decoder) { - console.log("Vp9 decoder ready"); + console.log("Vp9 decoder ready"); - /* - decoder.processFrame(buffer, () => { - player.drawFrame(decoder.frameBuffer) - }) - */ + /* + decoder.processFrame(buffer, () => { + player.drawFrame(decoder.frameBuffer) + }) + */ } async function onOpusReady(decoder) { - console.log("Opus decoder ready"); + console.log("Opus decoder ready"); } \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 872e81375..f1c79723d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,9 +1,5 @@ import './style.css'; -import { loadVp9, loadOpus } from "./codec"; -import './websock'; - -loadVp9(); -loadOpus(); +import "./client"; const app = document.querySelector('#app')! diff --git a/src/websock.ts b/src/websock.ts index acd9c3b58..231bfafa8 100644 --- a/src/websock.ts +++ b/src/websock.ts @@ -9,6 +9,7 @@ export default class Websock { _eventHandlers: { [key in Keys]: Function }; _buf: Uint8Array[]; _status: any; + _latency: number; constructor(uri: string) { this._eventHandlers = { @@ -22,6 +23,11 @@ export default class Websock { this._websocket = new WebSocket(uri); this._websocket.onmessage = this._recv_message.bind(this); this._websocket.binaryType = "arraybuffer"; + this._latency = new Date().getTime(); + } + + latency(): number { + return this._latency; } sendMessage(data: any) { @@ -63,6 +69,7 @@ export default class Websock { } }, timeout); this._websocket.onopen = () => { + this._latency = new Date().getTime() - this._latency; this._status = "open"; console.debug(">> WebSock.onopen"); if (this._websocket?.protocol) { @@ -72,28 +79,26 @@ export default class Websock { } this._eventHandlers.open(); - console.debug("<< WebSock.onopen"); + console.info("WebSock.onopen"); resolve(this); }; this._websocket.onclose = (e) => { this._status = e; - console.debug(">> WebSock.onclose"); + console.error("WebSock.onclose: " + e); this._eventHandlers.close(e); - console.debug("<< WebSock.onclose"); reject(e); }; this._websocket.onerror = (e) => { this._status = e; - console.debug(">> WebSock.onerror: " + e); + console.error("WebSock.onerror: " + e); this._eventHandlers.error(e); - console.debug("<< WebSock.onerror: " + e); reject(e); }; }); } async next(timeout = 12000): Promise { - let func = ( + const func = ( resolve: (value: Uint8Array) => void, reject: (reason: any) => void, tm0: number @@ -102,7 +107,7 @@ export default class Websock { resolve(this._buf[0]); this._buf.splice(0, 1); } else { - if (this._status != 'open') { + if (this._status != "open") { reject(this._status); return; } @@ -134,7 +139,7 @@ export default class Websock { _recv_message(e: any) { if (e.data instanceof window.ArrayBuffer) { - let bytes = new Uint8Array(e.data); + const bytes = new Uint8Array(e.data); this._buf.push(bytes); } this._eventHandlers.message(e.data); @@ -146,13 +151,3 @@ export default class Websock { return hasher.digest(); } } - -let ws = new Websock("ws://207.148.17.15:21118"); -await ws.open(); -console.log("ws connected"); -// let punchHole = rendezvous.PunchHoleRequest.fromJSON({ id: '' }); -// ws.send_rendezvous(rendezvous.RendezvousMessage.fromJSON({ punchHole })); -let testNatRequest = rendezvous.TestNatRequest.fromJSON({ serial: 0 }); -ws.sendRendezvous({ testNatRequest }); -let msg = ws.parseRendezvous(await ws.next()); -console.log(msg);