mirror of
https://github.com/streamwall/streamwall.git
synced 2025-12-06 01:45:37 -05:00
Fix desyncs when multiple clients connected
This commit is contained in:
@@ -29,10 +29,19 @@ const base62 = baseX(
|
||||
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||
)
|
||||
|
||||
function rand62(len: number) {
|
||||
export function rand62(len: number) {
|
||||
return base62.encode(randomBytes(len))
|
||||
}
|
||||
|
||||
export function uniqueRand62(len: number, map: Map<string, unknown>) {
|
||||
let val = rand62(len)
|
||||
while (map.has(val)) {
|
||||
// Regenerate in case of a collision
|
||||
val = rand62(len)
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
async function hashToken62(token: string, salt: string) {
|
||||
const hashBuffer = await scrypt(token, salt, 24)
|
||||
return base62.encode(hashBuffer as Buffer)
|
||||
@@ -162,12 +171,7 @@ export class Auth extends EventEmitter<AuthEvents> {
|
||||
throw new Error(`invalid role: ${role}`)
|
||||
}
|
||||
|
||||
let tokenId = rand62(8)
|
||||
while (this.tokensById.has(tokenId)) {
|
||||
// Regenerate in case of an id collision
|
||||
tokenId = rand62(8)
|
||||
}
|
||||
|
||||
const tokenId = uniqueRand62(8, this.tokensById)
|
||||
const secret = rand62(24)
|
||||
const tokenHash = await hashToken62(secret, this.salt)
|
||||
const tokenData = {
|
||||
|
||||
@@ -16,12 +16,13 @@ import {
|
||||
stateDiff,
|
||||
type StreamwallRole,
|
||||
} from 'streamwall-shared'
|
||||
import { Auth, StateWrapper } from './auth.ts'
|
||||
import { Auth, StateWrapper, uniqueRand62 } from './auth.ts'
|
||||
import { loadStorage, type StorageDB } from './storage.ts'
|
||||
|
||||
export const SESSION_COOKIE_NAME = 's'
|
||||
|
||||
interface Client {
|
||||
clientId: string
|
||||
ws: WebSocket
|
||||
lastStateSent: any
|
||||
identity: AuthTokenInfo
|
||||
@@ -248,7 +249,7 @@ async function initApp({ baseURL, clientStaticPath }: AppOptions) {
|
||||
console.error('Failed to send Streamwall doc update')
|
||||
}
|
||||
for (const client of clients.values()) {
|
||||
if (client.identity.tokenId === origin) {
|
||||
if (client.clientId === origin) {
|
||||
continue
|
||||
}
|
||||
try {
|
||||
@@ -299,25 +300,39 @@ async function initApp({ baseURL, clientStaticPath }: AppOptions) {
|
||||
return
|
||||
}
|
||||
|
||||
const clientId = uniqueRand62(8, clients)
|
||||
const client: Client = {
|
||||
clientId,
|
||||
ws,
|
||||
lastStateSent: null,
|
||||
identity,
|
||||
}
|
||||
clients.set(identity.tokenId, client)
|
||||
clients.set(clientId, client)
|
||||
|
||||
const pingInterval = setInterval(() => {
|
||||
ws.ping()
|
||||
}, 20 * 1000)
|
||||
|
||||
ws.on('close', () => {
|
||||
clients.delete(identity.tokenId)
|
||||
clients.delete(clientId)
|
||||
clearInterval(pingInterval)
|
||||
|
||||
console.log('Client disconnected from', request.ip, client.identity)
|
||||
console.log(
|
||||
'Client',
|
||||
clientId,
|
||||
'disconnected from',
|
||||
request.ip,
|
||||
client.identity,
|
||||
)
|
||||
})
|
||||
|
||||
console.log('Client connected from', request.ip, client.identity)
|
||||
console.log(
|
||||
'Client',
|
||||
clientId,
|
||||
'connected from',
|
||||
request.ip,
|
||||
client.identity,
|
||||
)
|
||||
|
||||
handleMessage(async (rawData) => {
|
||||
let msg: ControlCommandMessage
|
||||
@@ -350,7 +365,7 @@ async function initApp({ baseURL, clientStaticPath }: AppOptions) {
|
||||
Y.applyUpdate(
|
||||
streamwallConn.stateDoc,
|
||||
new Uint8Array(rawData),
|
||||
identity.tokenId,
|
||||
clientId,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user