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.
This commit is contained in:
@ -9,6 +9,8 @@ import { Affiliations, getVideoAffiliations, getChannelAffiliations } from '../p
|
||||
import { getProsodyDomain } from '../prosody/config/domain'
|
||||
import { fillVideoCustomFields } from '../custom-fields'
|
||||
import { getChannelInfosById } from '../database/channel'
|
||||
import { ensureProsodyRunning } from '../prosody/ctl'
|
||||
import { isDebugMode } from '../debug'
|
||||
|
||||
// See here for description: https://modules.prosody.im/mod_muc_http_defaults.html
|
||||
interface RoomDefaults {
|
||||
@ -222,6 +224,33 @@ async function initApiRouter (options: RegisterServerOptions): Promise<Router> {
|
||||
}
|
||||
))
|
||||
|
||||
// router.get('/federation_server_infos', asyncMiddleware(
|
||||
// async (req: Request, res: Response, _next: NextFunction) => {
|
||||
// logger.info('federation_server_infos api call')
|
||||
// // TODO/FIXME: return server infos.
|
||||
// // TODO/FIXME: store these informations on the other side.
|
||||
// res.json({ ok: true })
|
||||
// }
|
||||
// ))
|
||||
|
||||
if (isDebugMode(options)) {
|
||||
// Only add this route if the debug mode is enabled at time of the server launch.
|
||||
// Note: the isDebugMode will be tested again when the API is called.
|
||||
// Note: we dont authenticate the user. We want this API to be callable from debug tools.
|
||||
// This should not be an issue, as debug_mode should only be available on dev environments.
|
||||
router.get('/restart_prosody', asyncMiddleware(
|
||||
async (req: Request, res: Response, _next: NextFunction) => {
|
||||
if (!isDebugMode(options)) {
|
||||
res.json({ ok: false })
|
||||
return
|
||||
}
|
||||
const restartProsodyInDebugMode = req.query.debugger === 'true'
|
||||
await ensureProsodyRunning(options, true, restartProsodyInDebugMode)
|
||||
res.json({ ok: true })
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
return router
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,8 @@ import { getBoshUri, getWSUri } from '../uri/webchat'
|
||||
import { getVideoLiveChatInfos } from '../federation/storage'
|
||||
import { LiveChatJSONLDAttribute } from '../federation/types'
|
||||
import { anonymousConnectionInfos, remoteAuthenticatedConnectionEnabled } from '../federation/connection-infos'
|
||||
// import { XMPPWsProxyServer } from '../xmpp-ws-proxy/server'
|
||||
// import { checkRemote } from '../xmpp-ws-proxy/check-remote'
|
||||
import * as path from 'path'
|
||||
const got = require('got')
|
||||
|
||||
@ -28,6 +30,7 @@ interface ProsodyProxyInfo {
|
||||
let currentProsodyProxyInfo: ProsodyProxyInfo | null = null
|
||||
let currentHttpBindProxy: ReturnType<typeof createProxyServer> | null = null
|
||||
let currentWebsocketProxy: ReturnType<typeof createProxyServer> | null = null
|
||||
let currentS2SWebsocketProxy: ReturnType<typeof createProxyServer> | null = null
|
||||
|
||||
async function initWebchatRouter (options: RegisterServerOptionsV5): Promise<Router> {
|
||||
const {
|
||||
@ -202,13 +205,9 @@ async function initWebchatRouter (options: RegisterServerOptionsV5): Promise<Rou
|
||||
page = page.replace(/{{REMOTE_BOSH_SERVICE_URL}}/g, remoteConnectionInfos?.anonymous?.boshUri ?? '')
|
||||
page = page.replace(/{{REMOTE_WS_SERVICE_URL}}/g, remoteConnectionInfos?.anonymous?.wsUri ?? '')
|
||||
page = page.replace(/{{REMOTE_ANONYMOUS_XMPP_SERVER}}/g, remoteConnectionInfos?.anonymous ? 'true' : 'false')
|
||||
// Note: to be able to connect to remote XMPP server, with a local account,
|
||||
// we must enable prosody-room-allow-s2s
|
||||
// (which is required, so we can use outgoing S2S from the authenticated virtualhost).
|
||||
// TODO: There should be another settings, rather than prosody-room-allow-s2s
|
||||
page = page.replace(
|
||||
/{{REMOTE_AUTHENTICATED_XMPP_SERVER}}/g,
|
||||
settings['prosody-room-allow-s2s'] && remoteConnectionInfos?.authenticated ? 'true' : 'false'
|
||||
remoteConnectionInfos?.authenticated ? 'true' : 'false'
|
||||
)
|
||||
page = page.replace(/{{AUTHENTICATION_URL}}/g, authenticationUrl)
|
||||
page = page.replace(/{{AUTOVIEWERMODE}}/g, autoViewerMode ? 'true' : 'false')
|
||||
@ -270,6 +269,29 @@ async function initWebchatRouter (options: RegisterServerOptionsV5): Promise<Rou
|
||||
currentWebsocketProxy.ws(request, socket, head)
|
||||
}
|
||||
})
|
||||
|
||||
registerWebSocketRoute({
|
||||
route: '/xmpp-websocket-s2s',
|
||||
handler: (request, socket, head) => {
|
||||
if (!currentS2SWebsocketProxy) {
|
||||
peertubeHelpers.logger.error('There is no current websocket s2s proxy, should not get here.')
|
||||
// no need to close the socket, Peertube will
|
||||
// (see https://github.com/Chocobozzz/PeerTube/issues/5752#issuecomment-1510870894)
|
||||
return
|
||||
}
|
||||
currentS2SWebsocketProxy.ws(request, socket, head)
|
||||
}
|
||||
})
|
||||
// registerWebSocketRoute({
|
||||
// route: '/xmpp-websocket-proxy',
|
||||
// handler: async (request, socket, head) => {
|
||||
// const remoteInstanceUrl = request.headers['peertube-livechat-ws-proxy-instance-url']
|
||||
// if (!await checkRemote(options, remoteInstanceUrl)) {
|
||||
// return
|
||||
// }
|
||||
// XMPPWsProxyServer.singleton(options).handleUpgrade(request, socket, head)
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
router.get('/prosody-list-rooms', asyncMiddleware(
|
||||
@ -345,6 +367,11 @@ async function disableProxyRoute ({ peertubeHelpers }: RegisterServerOptions): P
|
||||
currentWebsocketProxy.close()
|
||||
currentWebsocketProxy = null
|
||||
}
|
||||
if (currentS2SWebsocketProxy) {
|
||||
peertubeHelpers.logger.info('Closing the s2s websocket proxy...')
|
||||
currentS2SWebsocketProxy.close()
|
||||
currentS2SWebsocketProxy = null
|
||||
}
|
||||
} catch (err) {
|
||||
peertubeHelpers.logger.error('Seems that the http bind proxy close has failed: ' + (err as string))
|
||||
}
|
||||
@ -403,6 +430,28 @@ async function enableProxyRoute (
|
||||
currentWebsocketProxy.on('close', () => {
|
||||
logger.info('Got a close event for the websocket proxy')
|
||||
})
|
||||
|
||||
logger.info('Creating a new s2s websocket proxy')
|
||||
currentS2SWebsocketProxy = createProxyServer({
|
||||
target: 'http://localhost:' + prosodyProxyInfo.port + '/xmpp-websocket-s2s',
|
||||
ignorePath: true,
|
||||
ws: true
|
||||
})
|
||||
currentS2SWebsocketProxy.on('error', (err, req, res) => {
|
||||
// We must handle errors, otherwise Peertube server crashes!
|
||||
logger.error(
|
||||
'The s2s websocket proxy got an error ' +
|
||||
'(this can be normal if you updated/uninstalled the plugin, or shutdowned peertube while users were chatting): ' +
|
||||
err.message
|
||||
)
|
||||
if ('writeHead' in res) {
|
||||
res.writeHead(500)
|
||||
}
|
||||
res.end('')
|
||||
})
|
||||
currentS2SWebsocketProxy.on('close', () => {
|
||||
logger.info('Got a close event for the s2s websocket proxy')
|
||||
})
|
||||
}
|
||||
|
||||
interface WCRemoteConnectionInfos {
|
||||
|
Reference in New Issue
Block a user