zhzabcd commited on
Commit
326b2d9
·
verified ·
1 Parent(s): 65717ba

Upload 4 files

Browse files
Files changed (4) hide show
  1. Dockerfile +23 -0
  2. docker-compose.yml +10 -0
  3. index.js +139 -0
  4. 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
+ }