peertube-plugin-livechat/server/lib/xmpp-ws-proxy/server.ts
John Livingston 9a2da60b7d
Chat Federation (and a lot more) WIP:
Note: websocket s2s is not working yet, still WIP.

New Features

* Chat Federation:
  * You can now connect to a remote chat with your local account.
  * This remote connection is done using a custom implementation of [XEP-0468: WebSocket S2S](https://xmpp.org/extensions/xep-0468.html), using some specific discovering method (so that it will work without any DNS configuration).

Minor changes and fixes

* Possibility to debug Prosody in development environments.
* Using process.spawn instead of process.exec to launch Prosody (safer, and more optimal).
* Prosody AppImage: fix path mapping: we only map necessary /etc/ subdir, so that the AppImage can access to /etc/resolv.conf, /etc/hosts, ...
* Prosody AppImage: hidden debug mode to disable lua-unbound, that seems broken in some docker dev environments.
2023-05-31 16:52:47 +02:00

120 lines
4.0 KiB
TypeScript

// import type { RegisterServerOptions } from '@peertube/peertube-types'
// import type { IncomingMessage } from 'http'
// import type { Duplex } from 'stream'
// import { WebSocketServer, WebSocket } from 'ws'
// import { Socket } from 'net'
// FIXME: this method should not be necessary anymore, it was a proof of concept.
// interface ProxyLogger {
// debug: (s: string) => void
// info: (s: string) => void
// error: (s: string) => void
// }
// let xmppWsProxyServer: XMPPWsProxyServer | undefined
// class XMPPWsProxyServer {
// private readonly logger: ProxyLogger
// private readonly options: RegisterServerOptions
// private readonly wsProxyServer: WebSocketServer
// private prosodyPort: number | undefined
// private readonly connections: Map<WebSocket, Socket> = new Map<WebSocket, Socket>()
// constructor (options: RegisterServerOptions) {
// const logger = options.peertubeHelpers.logger
// this.logger = {
// debug: s => logger.debug('XMPP-WS-PROXY: ' + s),
// info: s => logger.info('XMPP-WS-PROXY: ' + s),
// error: s => logger.error('XMPP-WS-PROXY: ' + s)
// }
// this.options = options
// this.wsProxyServer = new WebSocketServer({ noServer: true, perMessageDeflate: false })
// }
// public handleUpgrade (request: IncomingMessage, incomingSocket: Duplex, head: Buffer): void {
// this.wsProxyServer.handleUpgrade(request, incomingSocket, head, ws => {
// this.handleUpgradeCallback(ws).then(() => {}, () => {})
// })
// }
// public async handleUpgradeCallback (ws: WebSocket): Promise<void> {
// this.logger.debug('Opening a Websocket Proxy connection')
// const port = await this.getProsodyPort()
// if (!port) {
// this.logger.error('No port configured for Prosody, closing the websocket stream')
// ws.close() // FIXME: add a code and error message
// return
// }
// // Opening a tcp connection to local Prosody:
// const prosodySocket = new Socket()
// this.connections.set(ws, prosodySocket)
// prosodySocket.connect(port, 'localhost', () => {
// // TODO: write the remote IP in the header line.
// prosodySocket.write('LIVECHAT-WS-PROXY\n')
// })
// prosodySocket.on('close', () => {
// ws.close()
// })
// prosodySocket.on('data', (data) => {
// ws.send(data)
// })
// ws.on('message', (data) => {
// // TODO: remove this log
// this.logger.debug('Receiving raw data')
// if (Array.isArray(data)) {
// data.forEach(chunck => {
// prosodySocket.write(chunck)
// })
// } else if (data instanceof ArrayBuffer) {
// prosodySocket.write(Buffer.from(data))
// } else {
// prosodySocket.write(data)
// }
// })
// ws.on('close', () => {
// this.logger.debug('Websocket connection is closed, closing socket')
// prosodySocket.end()
// })
// }
// private async getProsodyPort (): Promise<number> {
// if (this.prosodyPort) {
// return this.prosodyPort
// }
// const port = await this.options.settingsManager.getSetting('prosody-port') as string
// this.prosodyPort = parseInt(port)
// return this.prosodyPort
// }
// private async closeConnections (): Promise<void> {
// this.logger.debug('Closing XMPPWsProxyServer connections...')
// this.connections.forEach((socket, _ws) => {
// socket.end()
// // ws.terminate() // not necessary, socket close event should be called
// })
// // FIXME: wait for all connections to be closed...
// }
// static singleton (options: RegisterServerOptions): XMPPWsProxyServer {
// if (!xmppWsProxyServer) {
// xmppWsProxyServer = new XMPPWsProxyServer(options)
// }
// return xmppWsProxyServer
// }
// static async destroySingleton (): Promise<void> {
// if (!xmppWsProxyServer) { return }
// const server = xmppWsProxyServer
// xmppWsProxyServer = undefined
// await server.closeConnections()
// }
// }
// export {
// XMPPWsProxyServer
// }