9a2da60b7d
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.
120 lines
4.0 KiB
TypeScript
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
|
|
// }
|