mirror of
https://github.com/stablyai/orca.git
synced 2026-10-17 16:02:55 +00:00
132 lines
4.6 KiB
TypeScript
132 lines
4.6 KiB
TypeScript
import { randomBytes, randomUUID } from 'crypto'
|
|
import type { IncomingMessage } from 'http'
|
|
export { RUNTIME_RELAY_MAX_FRAME_BYTES } from '../shared/runtime-relay-limits'
|
|
|
|
export const RUNTIME_RELAY_PROTOCOL_VERSION = 1
|
|
export const RUNTIME_RELAY_WS_PATH = '/ws'
|
|
export const RUNTIME_RELAY_DEFAULT_PORT = 8787
|
|
export const RUNTIME_RELAY_ENROLLMENT_TOKEN_BYTES = 32
|
|
export const RUNTIME_RELAY_MAX_PENDING_CLIENTS_PER_SERVER = 64
|
|
export const RUNTIME_RELAY_MAX_ACTIVE_DATA_SOCKETS_PER_SERVER = 64
|
|
export const RUNTIME_RELAY_MAX_GLOBAL_PENDING_CLIENTS = 1024
|
|
export const RUNTIME_RELAY_MAX_GLOBAL_ACTIVE_DATA_SOCKETS = 1024
|
|
export const RUNTIME_RELAY_MAX_BOUND_SERVERS = 10_000
|
|
export const RUNTIME_RELAY_MAX_EARLY_FRAMES_PER_CONNECTION = 4
|
|
export const RUNTIME_RELAY_MAX_EARLY_BYTES_PER_CONNECTION = 4 * 1024 * 1024
|
|
export const RUNTIME_RELAY_MAX_TOTAL_EARLY_BYTES_PER_SERVER = 16 * 1024 * 1024
|
|
export const RUNTIME_RELAY_MAX_GLOBAL_EARLY_BYTES = 64 * 1024 * 1024
|
|
export const RUNTIME_RELAY_MAX_FORWARD_BUFFERED_BYTES = 8 * 1024 * 1024
|
|
export const RUNTIME_RELAY_MAX_CONTROL_BUFFERED_BYTES = 1024 * 1024
|
|
export const RUNTIME_RELAY_ATTACH_DEADLINE_MS = 15_000
|
|
export const RUNTIME_RELAY_HEARTBEAT_INTERVAL_MS = 15_000
|
|
export const RUNTIME_RELAY_STALE_SOCKET_TIMEOUT_MS = 45_000
|
|
|
|
const SERVER_ID_RE = /^[A-Za-z0-9_-]{16,128}$/
|
|
const CONNECTION_ID_RE = /^[A-Za-z0-9_-]{16,128}$/
|
|
const HOST_TOKEN_HASH_RE = /^[a-f0-9]{64}$/
|
|
const MIN_HOST_TOKEN_LENGTH = 32
|
|
|
|
export type RuntimeRelayRole = 'server' | 'client'
|
|
|
|
export type RuntimeRelayClientRequest = {
|
|
role: 'client'
|
|
serverId: string
|
|
}
|
|
|
|
export type RuntimeRelayServerRequest =
|
|
| {
|
|
role: 'server'
|
|
serverId: string
|
|
hostToken: string
|
|
enrollmentToken: string | null
|
|
connectionId: null
|
|
}
|
|
| {
|
|
role: 'server'
|
|
serverId: string
|
|
hostToken: string
|
|
enrollmentToken: string | null
|
|
connectionId: string
|
|
}
|
|
|
|
export type RuntimeRelayRequest = RuntimeRelayClientRequest | RuntimeRelayServerRequest
|
|
|
|
export type RelayControlMessage =
|
|
| { type: 'sync'; connectionIds: string[] }
|
|
| { type: 'connected'; connectionId: string }
|
|
| { type: 'disconnected'; connectionId: string }
|
|
|
|
export function createRelayConnectionId(): string {
|
|
return randomUUID().replace(/-/g, '')
|
|
}
|
|
|
|
export function createRelayEnrollmentToken(): string {
|
|
return randomBytes(RUNTIME_RELAY_ENROLLMENT_TOKEN_BYTES).toString('base64url')
|
|
}
|
|
|
|
export function isRuntimeRelayServerId(value: unknown): value is string {
|
|
return typeof value === 'string' && SERVER_ID_RE.test(value)
|
|
}
|
|
|
|
export function isRuntimeRelayHostTokenHash(value: unknown): value is string {
|
|
return typeof value === 'string' && HOST_TOKEN_HASH_RE.test(value)
|
|
}
|
|
|
|
export function parseRuntimeRelayRequest(
|
|
request: IncomingMessage
|
|
): { ok: true; value: RuntimeRelayRequest } | { ok: false; statusCode: number; reason: string } {
|
|
const host = request.headers.host ?? '127.0.0.1'
|
|
let url: URL
|
|
try {
|
|
url = new URL(request.url ?? '/', `http://${host}`)
|
|
} catch {
|
|
return { ok: false, statusCode: 400, reason: 'invalid_url' }
|
|
}
|
|
if (url.pathname !== RUNTIME_RELAY_WS_PATH) {
|
|
return { ok: false, statusCode: 404, reason: 'not_found' }
|
|
}
|
|
if (url.searchParams.get('v') !== String(RUNTIME_RELAY_PROTOCOL_VERSION)) {
|
|
return { ok: false, statusCode: 400, reason: 'invalid_version' }
|
|
}
|
|
const role = url.searchParams.get('role')
|
|
const serverId = url.searchParams.get('serverId')
|
|
if ((role !== 'server' && role !== 'client') || !isRuntimeRelayServerId(serverId)) {
|
|
return { ok: false, statusCode: 400, reason: 'invalid_relay_request' }
|
|
}
|
|
if (role === 'client') {
|
|
return { ok: true, value: { role, serverId } }
|
|
}
|
|
const hostToken = parseHostAuthorization(request)
|
|
if (!hostToken || hostToken.length < MIN_HOST_TOKEN_LENGTH) {
|
|
return { ok: false, statusCode: 401, reason: 'invalid_host_token' }
|
|
}
|
|
const connectionId = url.searchParams.get('connectionId')
|
|
if (connectionId !== null && !CONNECTION_ID_RE.test(connectionId)) {
|
|
return { ok: false, statusCode: 400, reason: 'invalid_connection_id' }
|
|
}
|
|
return {
|
|
ok: true,
|
|
value: {
|
|
role,
|
|
serverId,
|
|
hostToken,
|
|
enrollmentToken: parseEnrollmentToken(request),
|
|
connectionId
|
|
}
|
|
}
|
|
}
|
|
|
|
function parseHostAuthorization(request: IncomingMessage): string | null {
|
|
const authorization = request.headers.authorization
|
|
if (!authorization) {
|
|
return null
|
|
}
|
|
const match = /^Bearer\s+(.+)$/i.exec(authorization.trim())
|
|
return match?.[1] ?? null
|
|
}
|
|
|
|
function parseEnrollmentToken(request: IncomingMessage): string | null {
|
|
const value = request.headers['x-orca-relay-enrollment']
|
|
return typeof value === 'string' && value.trim().length > 0 ? value : null
|
|
}
|