{"version":3,"sources":["communication-interface.ts"],"sourcesContent":["import { ProtocolDataType } from \"../compiler/protocol_types.ts\";\nimport { BROADCAST } from \"../types/addressing.ts\";\nimport { Endpoint } from \"../types/addressing.ts\";\nimport { Logger } from \"../utils/logger.ts\";\nimport { COM_HUB_SECRET, communicationHub } from \"./communication-hub.ts\";\nimport { IOHandler } from \"../runtime/io_handler.ts\";\nimport { LOCAL_ENDPOINT } from \"../types/addressing.ts\";\nimport { Runtime } from \"../runtime/runtime.ts\";\nimport type { dxb_header } from \"../utils/global_types.ts\";\nimport { Crypto } from \"../runtime/crypto.ts\";\n\nexport enum InterfaceDirection {\n    /**\n     * Supported communication direction: only receive\n     */\n    IN,\n    /**\n     * Supported communication direction: only send\n     */\n    OUT,\n    /**\n     * Supported communication directions: send and receive\n     */\n    IN_OUT\n}\n\nexport type InterfaceProperties =  {\n    type: string,\n    name?: string,\n\n    /**\n     * Supported communication directions\n     */\n    direction: InterfaceDirection,\n    /**\n     * Time in milliseconds to wait before reconnecting after a connection error\n     */\n    reconnectInterval?: number,\n    /**\n     * Estimated mean latency for this interface type in milliseconds (round trip time).\n     * Lower latency interfaces are preferred over higher latency channels\n     */\n    latency: number,\n    /**\n     * Bandwidth in bytes per second\n     */\n    bandwidth: number,\n\n    /**\n     * If true, the interface does not support continuous connections.\n     * All sockets are indirectly connected\n     */\n    noContinuousConnection?: boolean,\n\n    /**\n     * If true, the interface can be used to redirect DATEX messages to other endpoints\n     * which are not directly connected to the interface (default: true)\n     * Currently only enforced for broadcast messages\n     */\n    allowRedirects?: boolean\n}\n\nfunction getIdentifier(properties?: InterfaceProperties) {\n    if (!properties) return \"unknown\";\n    return `${properties.type}${properties.name? ` (${properties.name})` : ''}`\n}\n\nexport class EndpointConnectEvent extends Event {\n    constructor(public endpoint: Endpoint) {\n        super('connect');\n    }\n}\nexport class EndpointBeforeChangeEvent extends Event {\n    constructor(public endpoint: Endpoint) {\n        super('beforechange')\n    }\n}\nexport class BrokenChannelEvent extends Event {\n    constructor() {\n        super('brokenchannel')\n    }\n}\n\n\ninterface CustomEventMap {\n    \"connect\": EndpointConnectEvent\n    \"beforechange\": EndpointBeforeChangeEvent,\n    \"brokenchannel\": BrokenChannelEvent\n}\n\n/**\n * A connected communication interface socket that is registered in the communication hub\n * and can be used to send and receive messages\n */\nexport type ConnectedCommunicationInterfaceSocket = CommunicationInterfaceSocket & {\n    connected: true,\n    endpoint: Endpoint,\n    channelFactor: number,\n    interfaceProperties: InterfaceProperties\n}\n\n\ntype ReadonlySet<T> = Set<T> & {add: never, delete: never, clear: never}\n\n\n\nexport abstract class CommunicationInterfaceSocket extends EventTarget {\n    /**\n     * Endpoint is only set once. If the endpoint changes, a new socket is created\n     */\n    #endpoint?: Endpoint\n    #connected = false\n    #destroyed = false;\n    #opened = false;\n\n    clone?: CommunicationInterfaceSocket\n\n    static defaultLogger = new Logger(\"CommunicationInterfaceSocket\")\n    public logger = CommunicationInterfaceSocket.defaultLogger;\n\n    public readonly uuid: string = globalThis.crypto.randomUUID();\n\n    #connectTimestamp = Date.now();\n\n    get connectTimestamp() {\n        return this.#connectTimestamp\n    }\n\n    /**\n     * Calculated value describing the properties of the interface channel,\n     * based on bandwidth and latency.\n     * Interfaces with higher channel factor are preferred.\n     */\n    get channelFactor() {\n        if (!this.interfaceProperties) return undefined;\n        return this.interfaceProperties.bandwidth / this.interfaceProperties.latency\n    }\n\n    interfaceProperties?: InterfaceProperties\n\n    get isRegistered() {\n        return communicationHub.handler.hasSocket(this)\n    }\n\n    get connected() {\n        return this.#connected\n    }\n    set connected(connected) {\n        if (connected === this.#connected) return; // no change\n        if (this.#destroyed) throw new Error(\"Cannot change connected state of destroyed socket.\")\n        this.#connected = connected\n        this.#updateRegistration();\n    }\n\n    get endpoint(): Endpoint|undefined {\t\n        return this.#endpoint\n    }\n\n    set endpoint(endpoint: Endpoint) {\n        if (this.#endpoint) throw new Error(\"Cannot change endpoint of socket. Create a new socket instead.\")\n        this.#endpoint = endpoint\n        this.#updateRegistration();\n    }\n\n    /**\n     * Adds or removes the socket from the communication hub based\n     * on the connection state and endpoint availability\n     */\n    #updateRegistration() {\n        // handle open/close\n        if (this.#opened && !this.#connected) {\n            this.#opened = false;\n            this.close()\n        }\n        else if (!this.#opened && this.#connected) {\n            this.open()\n            this.#opened = true;\n        }\n\n        if (!this.#endpoint || this.#destroyed) return;\n\n        if (this.#connected) {\n            if (!this.isRegistered) {\n                this.dispatchEvent(new EndpointConnectEvent(this.#endpoint))\n                communicationHub.handler.registerSocket(this as ConnectedCommunicationInterfaceSocket, undefined, {knownSince: this.#connectTimestamp, distance: 1})\n            }\n        }\n        else {\n            if (this.isRegistered) {\n                communicationHub.handler.unregisterSocket(this)\n            }\n        }\n    }\n\n    public get canSend() {\n        return this.interfaceProperties?.direction !== InterfaceDirection.IN\n    }\n    public get canReceive() {\n        return this.interfaceProperties?.direction !== InterfaceDirection.OUT\n    }\n\n    public sendHello(dxb: ArrayBuffer) {\n        if (!Runtime.endpoint || Runtime.endpoint == LOCAL_ENDPOINT) return;\n        this.sendBlock(dxb).catch(console.error)\n    }\n\n    public sendGoodbye(dxb: ArrayBuffer) {\n        if (!Runtime.endpoint || Runtime.endpoint == LOCAL_ENDPOINT) return;\n        this.sendBlock(dxb).catch(console.error)\n    }\n\n    public async sendBlock(dxb: ArrayBuffer) {\n        if (!this.canSend) throw new Error(\"Cannot send from an IN interface socket\");\n        if (this.#destroyed) throw new Error(\"Cannot send from destroyed socket.\")\n        if (!this.connected) throw new Error(\"Cannot send from disconnected socket\");\n\n        const successful = await this.send(dxb)\n        if (!successful) {\n            console.error(\"Failed to send block via \" + this + (this.endpoint ? ` - ${this.endpoint}`: \"\") + \" (channel broken). Disconnecting socket.\")\n            // send was not successful, meaning the channel is broken. Disconnect socket\n            this.dispatchEvent(new BrokenChannelEvent())\n            this.connected = false\n        }\n        return successful;\n    }\n\n    protected async receive(dxb: ArrayBuffer) {\n        if (!this.canReceive) throw new Error(\"Cannot receive on an OUT interface socket\");\n        if (this.#destroyed) throw new Error(\"Cannot receive on destroyed socket\");\n        if (!this.connected) throw new Error(\"Cannot receive on disconnected socket\");\n\n        let header: dxb_header;\n        try {\n            header = await communicationHub.handler.datexIn({\n                dxb,\n                socket: this\n            })\n            IOHandler.handleDatexReceived(header, dxb, this)\n        }\n        catch (e) {\n            console.error(e);\n            return;\n        }\n        // a cloned socket was already created in the meantime, handle header in clone\n        if (this.clone) {\n            this.clone.handleReceiveHeader(header)\n        }\n        // handle header in this socket\n        else this.handleReceiveHeader(header)\n    }\n\n    protected handleReceiveHeader(header: dxb_header) {\n        if (this.#destroyed) return;\n        if (!this.connected) return;\n\n        if (this.endpoint) {\n            // received GOODBYE message, assume endpoint switch. If endpoint just disconnects\n            // this will be recognized when the socket is disconnected\n            if (header.type == ProtocolDataType.GOODBYE && header.sender === this.endpoint) {\n                this.connected = false\n                this.#destroyed = true\n                this.dispatchEvent(new EndpointBeforeChangeEvent(this.endpoint))\n            }\n            // message from another endpoint, record as indirect socket connection\n            else if (header.sender !== this.endpoint && !communicationHub.handler.hasSocket(this as ConnectedCommunicationInterfaceSocket, header.sender)) {\n                if (header.sender === Runtime.endpoint) {\n                    // loopback connection to own endpoint, this is not a problem, but might help with debugging\n                    this.logger.debug(\"Indirect connection to own endpoint detected at \" + this + \" (loopback)\");\n                }\n                else {\n                    const ttl = header.routing?.ttl;\n                    const maxTTL = header.routing?.prio;\n                    const hops = (maxTTL??0) - (ttl??0);\n                    this.logger.debug(\"New indirect connection detected at \" + this + \" (from \" + header.sender + \" - ttl:\" + ttl + \"/\" + maxTTL + \" hops:\" + hops + \")\");\n                    if (!header.timestamp) this.logger.warn(\"header timestamp missing for indirect connection to \" + header.sender);\n                    communicationHub.handler.registerSocket(this as ConnectedCommunicationInterfaceSocket, header.sender, {knownSince: header.timestamp?.getTime() || Date.now(), distance: hops})\n                }\n            }\n        }\n        // detect new endpoint\n        else if (header.sender) {\n            if (!header.timestamp) this.logger.warn(\"header timestamp missing for direct connection to \" + header.sender)\n            this.#connectTimestamp = header.timestamp?.getTime() || Date.now();\n            this.endpoint = header.sender\n        }\n    }\n\n\n    /**\n     * Send a DATEX block via this interface\n     * @param datex\n     * @param to \n     */\n    protected abstract send(datex:ArrayBuffer): Promise<boolean>|boolean\n\n    protected abstract open(): void\n    protected abstract close(): void\n\n    toString() {\n        return getIdentifier(this.interfaceProperties)\n    }\n\n\n    declare addEventListener: <K extends keyof CustomEventMap>(type: K, listener: (ev: CustomEventMap[K]) => void) => void;\n    declare removeEventListener: <K extends keyof CustomEventMap>(type: K, listener: (ev: CustomEventMap[K]) => void) => void;\n    declare dispatchEvent: <K extends keyof CustomEventMap>(ev: CustomEventMap[K]) => boolean;\n}\n\n\n/**\n * Base class for all DATEX communication interfaces\n */\nexport abstract class CommunicationInterface<Socket extends CommunicationInterfaceSocket = CommunicationInterfaceSocket> extends EventTarget {\n\n    protected logger = new Logger(this.constructor.name)\n\n    #sockets = new Set<Socket>()\n\n    abstract properties: InterfaceProperties\n\n    abstract connect(): boolean|Promise<boolean>\n    abstract disconnect(): void|Promise<void>\n\n    #connecting = false;\n\n    /**\n     * @private\n     */\n    async init(secret: symbol, timeout?: number) {\n\n        if (secret !== COM_HUB_SECRET) throw new Error(\"Directly calling CommunicationInterface.init() is not allowed\")\n        // if (Runtime.endpoint == LOCAL_ENDPOINT) throw new Error(\"Cannot use communication interface with local endpoint\")\n        \n        // return false if not connected after timeout\n        if (timeout) {\n            return Promise.race([\n                this.#connectLoop().then(() => true),\n                new Promise<boolean>(resolve => {\n                    setTimeout(() => {\n                        resolve(false)\n                    }, timeout)\n                })\n            ])\n        }\n        // no timeout\n        else {\n            await this.#connectLoop();\n            return true;\n        }\n    }\n\n    /**\n     * @private\n     */\n    async deinit(secret: symbol) {\n        if (secret !== COM_HUB_SECRET) throw new Error(\"Directly calling CommunicationInterface.deinit() is not allowed\")\n        this.clearSockets()\n        await this.disconnect()\n    }\n\n    getSockets(): ReadonlySet<Socket> {\n        return this.#sockets as ReadonlySet<Socket>\n    }\n\n\n    #connectHandler: ((endpoint: EndpointConnectEvent) => void)|null|undefined\n\n    /**\n     * Event handler that is called when a new endpoint is connected to a socket on this interface\n     */\n    set onConnect(handler: ((endpoint: EndpointConnectEvent) => void)|null|undefined) {\n        if (handler) {\n            this.#connectHandler = handler\n            this.addEventListener(\"connect\", handler)\n        }\n        else {\n            if (this.#connectHandler) this.removeEventListener(\"connect\", this.#connectHandler)\n            this.#connectHandler = handler\n        }\n    }\n\n    async #connectLoop(reconnecting = false) {\n        if (this.#connecting) return;\n        this.#connecting = true;\n        while (!await this.connect()) {\n            const interval = this.properties.reconnectInterval || 3000;\n            reconnecting = true;\n            this.logger.error(\"Could not connect to \" + this + \", trying again in \" + Math.round(interval/1000) + \"s\");\n            await sleep(interval)\n        }\n        if (reconnecting) this.logger.success(\"Reconnected to \" + this);\n        else this.logger.debug(\"Connected to \" + this);\n        this.#connecting = false;\n    }\n\n    protected async onConnectionError() {\n        this.logger.error(\"Connection error (\" + this + \")\");\n        this.clearSockets();\n        await this.#connectLoop(true)\n    }\n    \n    /**\n     * Create a new socket for this interface\n     */\n    protected async addSocket(socket: Socket) {\n        if (this.#sockets.has(socket)) throw new Error(\"Socket already part of interface sockets.\")\n\n        // endpoint will change (or socket is disconnected completely), propagate event and clone socket\n        socket.addEventListener('beforechange', e => {\n            this.dispatchEvent(new EndpointBeforeChangeEvent(e.endpoint))\n            // remove old socket\n            this.removeSocket(socket)\n            // clone and add new socket\n            const newSocket = this.cloneSocket(socket);\n            socket.clone = newSocket;\n            this.addSocket(newSocket);\n        })\n\n        // endpoint connected, propagate event\n        socket.addEventListener('connect', e => {\n            this.dispatchEvent(new EndpointConnectEvent(e.endpoint))\n        })\n\n        // channel broken, remove socket\n        socket.addEventListener('brokenchannel', () => {\n            this.removeSocket(socket)\n        });\n\n        // no direct endpoint connections supported, set socket endpoint to @@any to force only\n        // indirect connection registrations\n        if (this.properties.noContinuousConnection) {\n            socket.endpoint = BROADCAST\n        }\n\n        socket.interfaceProperties = this.properties\n        socket.logger = this.logger;\n        socket.connected = true; // adds sockets to communication hub\n        this.#sockets.add(socket);\n        // send HELLO message\n        if (socket.canSend) {\n            const helloMessage = await communicationHub.handler.compileHelloMessage()\n            if (helloMessage) socket.sendHello(helloMessage)\n        }\n    }\n\n    /**\n     * Create a new socket from an existing socket\n     * which is no longer connected to an endpoint\n     * @param socket \n     */\n    protected abstract cloneSocket(socket: Socket): Socket\n\n    /**\n     * Remove a socket from this interface\n     */\n    protected removeSocket(socket: Socket) {\n        if (!this.#sockets.has(socket)) {\n            return;\n            // throw new Error(\"Cannot remove socket, not part of interface sockets.\")\n        }\n        this.#sockets.delete(socket)\n        socket.connected = false; // removes socket from communication hub\n    } \n\n    /**\n     * Remove all sockets from this interface\n     */\n    protected clearSockets() {\n        for (const socket of this.#sockets) {\n            this.removeSocket(socket)\n        }\n    }\n\n    toString() {\n        return getIdentifier(this.properties)\n    }\n\n    declare addEventListener: <K extends keyof CustomEventMap>(type: K, listener: (ev: CustomEventMap[K]) => void) => void;\n    declare removeEventListener: <K extends keyof CustomEventMap>(type: K, listener: (ev: CustomEventMap[K]) => void) => void;\n    declare dispatchEvent: <K extends keyof CustomEventMap>(ev: CustomEventMap[K]) => boolean;\n}\n"],"names":["InterfaceDirection","ProtocolDataType","BROADCAST","Logger","COM_HUB_SECRET","communicationHub","IOHandler","LOCAL_ENDPOINT","Runtime","getIdentifier","properties","type","name","EndpointConnectEvent","Event","constructor","endpoint","EndpointBeforeChangeEvent","BrokenChannelEvent","CommunicationInterfaceSocket","EventTarget","clone","defaultLogger","logger","uuid","globalThis","crypto","randomUUID","Date","now","connectTimestamp","channelFactor","interfaceProperties","bandwidth","latency","isRegistered","handler","hasSocket","connected","Error","close","open","dispatchEvent","registerSocket","undefined","knownSince","distance","unregisterSocket","canSend","direction","canReceive","sendHello","dxb","sendBlock","catch","console","error","sendGoodbye","successful","send","receive","header","datexIn","socket","handleDatexReceived","e","handleReceiveHeader","GOODBYE","sender","debug","ttl","routing","maxTTL","prio","hops","timestamp","warn","getTime","toString","CommunicationInterface","Set","init","secret","timeout","Promise","race","then","resolve","setTimeout","deinit","clearSockets","disconnect","getSockets","onConnect","addEventListener","removeEventListener","reconnecting","connect","interval","reconnectInterval","Math","round","sleep","success","onConnectionError","addSocket","has","removeSocket","newSocket","cloneSocket","noContinuousConnection","add","helloMessage","compileHelloMessage","delete"],"mappings":"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","sourceRoot":"/lib/datex-core-js-legacy-0.3.15/network/","file":"communication-interface.ts"}