http ingest
This commit is contained in:
@@ -1,15 +1,16 @@
|
|||||||
import type { IncomingMessage } from 'http'
|
import type { IncomingMessage } from 'http'
|
||||||
|
import { createServer } from 'http'
|
||||||
import { WebSocket, WebSocketServer } from 'ws'
|
import { WebSocket, WebSocketServer } from 'ws'
|
||||||
|
|
||||||
import { log } from '../helpers/log.js'
|
import { log } from '../helpers/log.js'
|
||||||
import { lastTopicSegment } from '../helpers/topic-match.js'
|
import { lastTopicSegment } from '../helpers/topic-match.js'
|
||||||
|
|
||||||
const wsPipePort = Number(process.env.WS_PIPE_PORT)
|
const wsPipePort = Number(process.env.WS_PIPE_PORT)
|
||||||
|
const httpIngestPort = Number(process.env.HTTP_INGEST_PORT) // новый порт, например 3456
|
||||||
const LOG_INTERVAL_MS = 10_000
|
const LOG_INTERVAL_MS = 10_000
|
||||||
|
|
||||||
const wss = new WebSocketServer({ port: wsPipePort, perMessageDeflate: false })
|
const wss = new WebSocketServer({ port: wsPipePort, perMessageDeflate: false })
|
||||||
|
|
||||||
const producersByChannel = new Map<string, WebSocket>()
|
|
||||||
const viewersByChannel = new Map<string, Set<WebSocket>>()
|
const viewersByChannel = new Map<string, Set<WebSocket>>()
|
||||||
const lastLogByChannel = new Map<string, number>()
|
const lastLogByChannel = new Map<string, number>()
|
||||||
|
|
||||||
@@ -41,26 +42,37 @@ function logThroughput(channel: string, bytes: number): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleProducer(ws: WebSocket, channel: string): void {
|
// --- HTTP ingest ---
|
||||||
const existing = producersByChannel.get(channel)
|
const httpIngest = createServer((req: IncomingMessage, res) => {
|
||||||
if (existing?.readyState === WebSocket.OPEN) {
|
const path = req.url?.split('?')[0] ?? ''
|
||||||
existing.close(1000, 'replaced')
|
|
||||||
}
|
|
||||||
producersByChannel.set(channel, ws)
|
|
||||||
|
|
||||||
ws.on('message', (data, isBinary) => {
|
if (!path.startsWith('/in/')) {
|
||||||
if (!isBinary) return
|
res.writeHead(404).end()
|
||||||
const chunk = Buffer.isBuffer(data) ? data : Buffer.from(data as ArrayBuffer)
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const channel = lastTopicSegment(path)
|
||||||
|
log(`pipe.in.http_connected [${channel}]`)
|
||||||
|
|
||||||
|
req.on('data', (chunk: Buffer) => {
|
||||||
logThroughput(channel, chunk.length)
|
logThroughput(channel, chunk.length)
|
||||||
broadcast(channel, chunk)
|
broadcast(channel, chunk)
|
||||||
})
|
})
|
||||||
|
|
||||||
ws.on('close', () => {
|
req.on('end', () => {
|
||||||
if (producersByChannel.get(channel) === ws) {
|
log(`pipe.in.http_disconnected [${channel}]`)
|
||||||
producersByChannel.delete(channel)
|
res.writeHead(200).end()
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
req.on('error', (err) => {
|
||||||
|
log(`pipe.in.http_error [${channel}]`, err)
|
||||||
|
res.writeHead(500).end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
httpIngest.listen(httpIngestPort, () => {
|
||||||
|
log('pipe.http_ingest_started', { port: httpIngestPort })
|
||||||
|
})
|
||||||
|
|
||||||
function handleViewer(ws: WebSocket, channel: string, path: string): void {
|
function handleViewer(ws: WebSocket, channel: string, path: string): void {
|
||||||
log(`pipe.out.connection ${path}`)
|
log(`pipe.out.connection ${path}`)
|
||||||
@@ -76,11 +88,6 @@ function handleViewer(ws: WebSocket, channel: string, path: string): void {
|
|||||||
wss.on('connection', (ws: WebSocket, req: IncomingMessage) => {
|
wss.on('connection', (ws: WebSocket, req: IncomingMessage) => {
|
||||||
const path = req.url?.split('?')[0] ?? ''
|
const path = req.url?.split('?')[0] ?? ''
|
||||||
|
|
||||||
if (path.startsWith('/in/')) {
|
|
||||||
handleProducer(ws, lastTopicSegment(path))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (path.startsWith('/out/')) {
|
if (path.startsWith('/out/')) {
|
||||||
handleViewer(ws, lastTopicSegment(path), path)
|
handleViewer(ws, lastTopicSegment(path), path)
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user