Spaces:
Sleeping
Sleeping
Upload 4 files
Browse files- Dockerfile +23 -0
- docker-compose.yml +10 -0
- index.js +139 -0
- package.json +13 -0
Dockerfile
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Use the official Node.js image as the base image
|
2 |
+
FROM node:16
|
3 |
+
|
4 |
+
# Set the working directory inside the container
|
5 |
+
WORKDIR /app
|
6 |
+
|
7 |
+
# Copy package.json and package-lock.json (if available)
|
8 |
+
COPY package*.json ./
|
9 |
+
|
10 |
+
# Install dependencies
|
11 |
+
RUN npm install
|
12 |
+
|
13 |
+
# Copy the rest of the application code
|
14 |
+
COPY . .
|
15 |
+
|
16 |
+
# Make the script executable
|
17 |
+
RUN chmod +x index.js
|
18 |
+
|
19 |
+
# Expose the port the app runs on
|
20 |
+
EXPOSE 4444
|
21 |
+
|
22 |
+
# Command to run the app
|
23 |
+
CMD ["node", "index.js"]
|
docker-compose.yml
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
version: '3.8'
|
2 |
+
|
3 |
+
services:
|
4 |
+
y-webrtc-signaling:
|
5 |
+
build: .
|
6 |
+
ports:
|
7 |
+
- "4444:4444"
|
8 |
+
environment:
|
9 |
+
- PORT=4444
|
10 |
+
restart: always
|
index.js
ADDED
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env node
|
2 |
+
|
3 |
+
import { WebSocketServer } from 'ws'
|
4 |
+
import http from 'http'
|
5 |
+
import * as map from 'lib0/map'
|
6 |
+
|
7 |
+
const wsReadyStateConnecting = 0
|
8 |
+
const wsReadyStateOpen = 1
|
9 |
+
const wsReadyStateClosing = 2 // eslint-disable-line
|
10 |
+
const wsReadyStateClosed = 3 // eslint-disable-line
|
11 |
+
|
12 |
+
const pingTimeout = 30000
|
13 |
+
|
14 |
+
const port = process.env.PORT || 4444
|
15 |
+
const wss = new WebSocketServer({ noServer: true })
|
16 |
+
|
17 |
+
const server = http.createServer((request, response) => {
|
18 |
+
response.writeHead(200, { 'Content-Type': 'text/plain' })
|
19 |
+
response.end('okay')
|
20 |
+
})
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Map froms topic-name to set of subscribed clients.
|
24 |
+
* @type {Map<string, Set<any>>}
|
25 |
+
*/
|
26 |
+
const topics = new Map()
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @param {any} conn
|
30 |
+
* @param {object} message
|
31 |
+
*/
|
32 |
+
const send = (conn, message) => {
|
33 |
+
if (conn.readyState !== wsReadyStateConnecting && conn.readyState !== wsReadyStateOpen) {
|
34 |
+
conn.close()
|
35 |
+
}
|
36 |
+
try {
|
37 |
+
conn.send(JSON.stringify(message))
|
38 |
+
} catch (e) {
|
39 |
+
conn.close()
|
40 |
+
}
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Setup a new client
|
45 |
+
* @param {any} conn
|
46 |
+
*/
|
47 |
+
const onconnection = conn => {
|
48 |
+
/**
|
49 |
+
* @type {Set<string>}
|
50 |
+
*/
|
51 |
+
const subscribedTopics = new Set()
|
52 |
+
let closed = false
|
53 |
+
// Check if connection is still alive
|
54 |
+
let pongReceived = true
|
55 |
+
const pingInterval = setInterval(() => {
|
56 |
+
if (!pongReceived) {
|
57 |
+
conn.close()
|
58 |
+
clearInterval(pingInterval)
|
59 |
+
} else {
|
60 |
+
pongReceived = false
|
61 |
+
try {
|
62 |
+
conn.ping()
|
63 |
+
} catch (e) {
|
64 |
+
conn.close()
|
65 |
+
}
|
66 |
+
}
|
67 |
+
}, pingTimeout)
|
68 |
+
conn.on('pong', () => {
|
69 |
+
pongReceived = true
|
70 |
+
})
|
71 |
+
conn.on('close', () => {
|
72 |
+
subscribedTopics.forEach(topicName => {
|
73 |
+
const subs = topics.get(topicName) || new Set()
|
74 |
+
subs.delete(conn)
|
75 |
+
if (subs.size === 0) {
|
76 |
+
topics.delete(topicName)
|
77 |
+
}
|
78 |
+
})
|
79 |
+
subscribedTopics.clear()
|
80 |
+
closed = true
|
81 |
+
})
|
82 |
+
conn.on('message', /** @param {object} message */ message => {
|
83 |
+
if (typeof message === 'string' || message instanceof Buffer) {
|
84 |
+
message = JSON.parse(message)
|
85 |
+
}
|
86 |
+
if (message && message.type && !closed) {
|
87 |
+
switch (message.type) {
|
88 |
+
case 'subscribe':
|
89 |
+
/** @type {Array<string>} */ (message.topics || []).forEach(topicName => {
|
90 |
+
if (typeof topicName === 'string') {
|
91 |
+
// add conn to topic
|
92 |
+
const topic = map.setIfUndefined(topics, topicName, () => new Set())
|
93 |
+
topic.add(conn)
|
94 |
+
// add topic to conn
|
95 |
+
subscribedTopics.add(topicName)
|
96 |
+
}
|
97 |
+
})
|
98 |
+
break
|
99 |
+
case 'unsubscribe':
|
100 |
+
/** @type {Array<string>} */ (message.topics || []).forEach(topicName => {
|
101 |
+
const subs = topics.get(topicName)
|
102 |
+
if (subs) {
|
103 |
+
subs.delete(conn)
|
104 |
+
}
|
105 |
+
})
|
106 |
+
break
|
107 |
+
case 'publish':
|
108 |
+
if (message.topic) {
|
109 |
+
const receivers = topics.get(message.topic)
|
110 |
+
if (receivers) {
|
111 |
+
message.clients = receivers.size
|
112 |
+
receivers.forEach(receiver =>
|
113 |
+
send(receiver, message)
|
114 |
+
)
|
115 |
+
}
|
116 |
+
}
|
117 |
+
break
|
118 |
+
case 'ping':
|
119 |
+
send(conn, { type: 'pong' })
|
120 |
+
}
|
121 |
+
}
|
122 |
+
})
|
123 |
+
}
|
124 |
+
wss.on('connection', onconnection)
|
125 |
+
|
126 |
+
server.on('upgrade', (request, socket, head) => {
|
127 |
+
// You may check auth of request here..
|
128 |
+
/**
|
129 |
+
* @param {any} ws
|
130 |
+
*/
|
131 |
+
const handleAuth = ws => {
|
132 |
+
wss.emit('connection', ws, request)
|
133 |
+
}
|
134 |
+
wss.handleUpgrade(request, socket, head, handleAuth)
|
135 |
+
})
|
136 |
+
|
137 |
+
server.listen(port)
|
138 |
+
|
139 |
+
console.log('Signaling server running on localhost:', port)
|
package.json
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "y-webrtc-signaling",
|
3 |
+
"version": "1.0.0",
|
4 |
+
"description": "WebRTC provider for Yjs",
|
5 |
+
"main": "./index.js",
|
6 |
+
"sideEffects": false,
|
7 |
+
"type": "module",
|
8 |
+
"license": "MIT",
|
9 |
+
"dependencies": {
|
10 |
+
"lib0": "^0.2.42",
|
11 |
+
"ws": "^8.14.2"
|
12 |
+
}
|
13 |
+
}
|