Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561
with:
always-auth: true
node-version: 16.x
node-version: 18.x

- name: Get npm cache directory
id: npm-cache-dir
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:16 as base
FROM node:18 as base

WORKDIR /home/node/app

Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# Signaling server
# Signaling Server

[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)

## Development Setup

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"@types/node": "^18.6.2",
"@types/prometheus-gc-stats": "^0.6.2",
"@types/sinon": "^10.0.13",
"@types/ws": "^8.5.3",
"@types/ws": "^8.5.4",
"chai": "^4.3.6",
"clinic": "^11.1.2",
"mocha": "^10.0.0",
Expand All @@ -40,7 +40,7 @@
"prometheus-gc-stats": "^0.6.3",
"rxjs": "^7.5.6",
"tslog": "^4.8.2",
"uWebSockets.js": "uNetworking/uWebSockets.js#v20.10.0",
"uWebSockets.js": "uNetworking/uWebSockets.js#v20.30.0",
"zod": "^3.17.10"
}
}
48 changes: 32 additions & 16 deletions src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ import {
RemoteData,
} from './messages/_types'

type Data = {
id: string
connectionId: string
source: string
targetClient: string
}

const collectDefaultMetrics = prometheusClient.collectDefaultMetrics
collectDefaultMetrics()

Expand Down Expand Up @@ -83,7 +90,7 @@ const server = async () => {
return !!(await redis.publisher.sIsMember(key, value))
}

const subscribe = async (ws: uWs.WebSocket, dataChanel: string) => {
const subscribe = async (ws: uWs.WebSocket<any>, dataChanel: string) => {
const t0 = performance.now()
await redis.subscriber.subscribe(dataChanel, (raw) => {
parseJSON<
Expand All @@ -100,7 +107,7 @@ const server = async () => {
redisSubscribeTime.set(t1 - t0)
}

const send = (ws: uWs.WebSocket, message: MessageTypes) => {
const send = (ws: uWs.WebSocket<any>, message: MessageTypes) => {
try {
log.trace({
event: 'SendWSMessage',
Expand All @@ -121,6 +128,9 @@ const server = async () => {
uWs
.App()
.ws('/*', {
sendPingsAutomatically: true,
idleTimeout: 0,
maxLifetime: 0,
upgrade: (res, req, context) => {
res.upgrade(
{
Expand All @@ -133,11 +143,12 @@ const server = async () => {
context
)
},
open: async (ws) => {
open: async (ws: uWs.WebSocket<Data>) => {
try {
console.log(ws)
++connections
connectedClientsGauge.set(connections)
const url: URL = ws.url
const url: URL = (ws as any).url
const connectionId = url.pathname.slice(1)
const target = url.searchParams.get('target')
const source = url.searchParams.get('source')
Expand All @@ -162,15 +173,15 @@ const server = async () => {
}

const websocketId = randomUUID()
ws.id = websocketId
ws.connectionId = connectionId
ws.source = source
ws.targetClient = `${ws.connectionId}:${target}`
ws.getUserData().id = websocketId
ws.getUserData().connectionId = connectionId
ws.getUserData().source = source
ws.getUserData().targetClient = `${connectionId}:${target}`

const [, , targetWebsocketIds] = await Promise.all([
subscribe(ws, websocketId),
setData(`${connectionId}:${source}`, websocketId),
getTargetWebsocketIds(ws.targetClient),
getTargetWebsocketIds(ws.getUserData().targetClient),
])

log.trace({
Expand Down Expand Up @@ -227,11 +238,13 @@ const server = async () => {
})
}

if (await isMember(ws.targetClient, parsed.targetClientId)) {
if (
await isMember(ws.getUserData().targetClient, parsed.targetClientId)
) {
await publish(parsed.targetClientId, {
info: 'remoteData',
data: parsed,
remoteClientId: ws.id,
remoteClientId: ws.getUserData().id,
requestId: parsed.requestId,
})
} else {
Expand All @@ -253,24 +266,27 @@ const server = async () => {
--connections
connectedClientsGauge.set(connections)
try {
if (ws.id) {
if (ws.getUserData().id) {
const targetWebsocketIds = await getTargetWebsocketIds(
ws.targetClient
ws.getUserData().targetClient
)
if (targetWebsocketIds && targetWebsocketIds.length) {
await Promise.all(
targetWebsocketIds.map((targetWebsocketId) =>
publish(targetWebsocketId, {
info: 'remoteClientDisconnected',
remoteClientId: ws.id,
remoteClientId: ws.getUserData().id,
})
)
)
}

await Promise.all([
redis.subscriber.unsubscribe(ws.id),
removeData(`${ws.connectionId}:${ws.source}`, ws.id),
redis.subscriber.unsubscribe(ws.getUserData().id),
removeData(
`${ws.getUserData().connectionId}:${ws.getUserData().source}`,
ws.getUserData().id
),
])
}

Expand Down
10 changes: 5 additions & 5 deletions src/utils/rate-limit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ const RateLimit = (limit: number, interval: number) => {
const last = Symbol() as unknown as string
const count = Symbol() as unknown as string
setInterval(() => ++now, interval)
return (ws: uWs.WebSocket) => {
if (ws[last] != now) {
ws[last] = now
ws[count] = 1
return (ws: uWs.WebSocket<any>) => {
if (ws.getUserData()[last] != now) {
ws.getUserData()[last] = now
ws.getUserData()[count] = 1
} else {
return ++ws[count] > limit
return ++ws.getUserData()[count] > limit
}
}
}
Expand Down
14 changes: 7 additions & 7 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -360,10 +360,10 @@
resolved "https://registry.yarnpkg.com/@types/webgl-ext/-/webgl-ext-0.0.30.tgz#0ce498c16a41a23d15289e0b844d945b25f0fb9d"
integrity sha512-LKVgNmBxN0BbljJrVUwkxwRYqzsAEPcZOe6S2T6ZaBDIrFp0qu4FNlpc5sM1tGbXUYFgdVQIoeLk1Y1UoblyEg==

"@types/ws@^8.5.3":
version "8.5.3"
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d"
integrity sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==
"@types/ws@^8.5.4":
version "8.5.4"
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.4.tgz#bb10e36116d6e570dd943735f86c933c1587b8a5"
integrity sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==
dependencies:
"@types/node" "*"

Expand Down Expand Up @@ -5315,9 +5315,9 @@ typescript@^4.7.4:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235"
integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==

uWebSockets.js@uNetworking/uWebSockets.js#v20.10.0:
version "20.10.0"
resolved "https://codeload.github.com/uNetworking/uWebSockets.js/tar.gz/806df48c9da86af7b3341f3e443388c7cd15c3de"
uWebSockets.js@uNetworking/uWebSockets.js#v20.30.0:
version "20.30.0"
resolved "https://codeload.github.com/uNetworking/uWebSockets.js/tar.gz/d39d4181daf5b670d44cbc1b18f8c28c85fd4142"

umd@^3.0.0:
version "3.0.3"
Expand Down