mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-06 03:20:13 +08:00
* create a new session when failed to connect to socket * reset termnal on connect
101 lines
2.3 KiB
JavaScript
101 lines
2.3 KiB
JavaScript
import { Server } from 'socket.io'
|
|
import { Session } from '@linux-odyssey/models'
|
|
import { getAndStartContainer, attachContainer } from '../containers/docker.js'
|
|
import SessionMiddleware from '../middleware/session.js'
|
|
import { genJWT } from '../utils/auth.js'
|
|
|
|
const sessions = new Map()
|
|
|
|
function listenToSession(sessionId, callback) {
|
|
const callbacks = sessions.get(sessionId) || []
|
|
sessions.set(sessionId, callbacks.concat(callback))
|
|
}
|
|
|
|
function removeFromSession(sessionId, event, callback) {
|
|
const callbacks = sessions.get((sessionId, event)) || []
|
|
sessions.set(
|
|
(sessionId, event),
|
|
callbacks.filter((cb) => cb !== callback)
|
|
)
|
|
}
|
|
|
|
export function pushToSession(sessionId, event, ...args) {
|
|
const callbacks = sessions.get(sessionId)
|
|
if (callbacks) {
|
|
callbacks.forEach((callback) => callback(event, ...args))
|
|
}
|
|
}
|
|
|
|
async function connectClient(socket) {
|
|
const user = socket.request.session?.passport?.user
|
|
if (!user) {
|
|
socket.send('User not found.')
|
|
socket.disconnect()
|
|
return
|
|
}
|
|
const sessionId = socket.handshake.query.session_id
|
|
if (!sessionId) {
|
|
socket.emit('error', 'Session ID not found.')
|
|
socket.disconnect()
|
|
return
|
|
}
|
|
|
|
const session = await Session.findOne({
|
|
_id: sessionId,
|
|
user,
|
|
status: 'active',
|
|
})
|
|
if (!session) {
|
|
socket.emit('error', 'Session not found.')
|
|
socket.disconnect()
|
|
return
|
|
}
|
|
|
|
const token = await genJWT({
|
|
session_id: session.id,
|
|
})
|
|
|
|
let container
|
|
let stream
|
|
try {
|
|
container = await getAndStartContainer(session.containerId)
|
|
stream = await attachContainer(container, { token })
|
|
} catch (err) {
|
|
socket.emit('error', 'Failed to start container.')
|
|
socket.disconnect()
|
|
return
|
|
}
|
|
|
|
stream.socket.on('data', (chunk) => {
|
|
socket.emit('terminal', chunk.toString())
|
|
})
|
|
|
|
socket.on('message', console.log)
|
|
|
|
socket.on('terminal', function incoming(message) {
|
|
stream.socket.write(message)
|
|
})
|
|
|
|
const socketCallback = (event, ...data) => {
|
|
socket.emit(event, ...data)
|
|
}
|
|
|
|
listenToSession(session.id, socketCallback)
|
|
|
|
socket.on('disconnect', () => {
|
|
stream.socket.write('exit\n')
|
|
removeFromSession(session.id, socketCallback)
|
|
stream.destroy()
|
|
})
|
|
|
|
socket.send(`${container.id}\n`)
|
|
}
|
|
|
|
export default (server) => {
|
|
const io = new Server(server)
|
|
|
|
io.engine.use(SessionMiddleware)
|
|
|
|
io.on('connection', connectClient)
|
|
}
|