@quakejs/master 1.0.16 → 1.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/master-client.js +116 -71
- package/master-server.js +17 -7
- package/package.json +1 -1
package/master-client.js
CHANGED
|
@@ -2,40 +2,36 @@ import MasterBase from './master-base.js';
|
|
|
2
2
|
|
|
3
3
|
class MasterClient extends MasterBase {
|
|
4
4
|
#onserver;
|
|
5
|
-
#master;
|
|
6
5
|
|
|
7
6
|
constructor (onserver) {
|
|
8
7
|
super();
|
|
9
8
|
|
|
10
9
|
this.#onserver = onserver;
|
|
11
|
-
this.#master = null;
|
|
12
10
|
}
|
|
13
11
|
|
|
14
12
|
subscribe (host, port) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if (this.#master) {
|
|
18
|
-
try {
|
|
19
|
-
this.#master.close();
|
|
20
|
-
} catch (e) {
|
|
21
|
-
console.error(e);
|
|
22
|
-
} finally {
|
|
23
|
-
this.#master = null;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
13
|
+
const session = new WebTransport(`${host}:${port}`);
|
|
26
14
|
|
|
27
|
-
|
|
15
|
+
/* prevent unhandled rejections before main loop */
|
|
16
|
+
session.ready.catch(() => {});
|
|
17
|
+
session.closed.catch(() => {});
|
|
28
18
|
|
|
29
19
|
(async () => {
|
|
30
20
|
try {
|
|
31
|
-
|
|
21
|
+
const sessionClosed = session.closed.then(
|
|
22
|
+
() => ({ done: true, value: null }),
|
|
23
|
+
(err) => { throw err; }
|
|
24
|
+
);
|
|
32
25
|
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
await session.ready;
|
|
27
|
+
|
|
28
|
+
const writer = session.datagrams.writable.getWriter();
|
|
29
|
+
const reader = session.datagrams.readable.getReader();
|
|
30
|
+
let resendTimeout;
|
|
35
31
|
|
|
36
32
|
/* send until a response is received */
|
|
37
33
|
const send = () => {
|
|
38
|
-
writer.write(this.encode('subscribe'));
|
|
34
|
+
writer.write(this.encode('subscribe')).catch(() => {});
|
|
39
35
|
|
|
40
36
|
resendTimeout = setTimeout(send, 1000);
|
|
41
37
|
};
|
|
@@ -44,7 +40,10 @@ class MasterClient extends MasterBase {
|
|
|
44
40
|
|
|
45
41
|
/* read responses */
|
|
46
42
|
while (true) {
|
|
47
|
-
const { done, value } = await
|
|
43
|
+
const { done, value } = await Promise.race([
|
|
44
|
+
reader.read(),
|
|
45
|
+
sessionClosed
|
|
46
|
+
]);
|
|
48
47
|
|
|
49
48
|
clearTimeout(resendTimeout);
|
|
50
49
|
|
|
@@ -62,100 +61,146 @@ class MasterClient extends MasterBase {
|
|
|
62
61
|
}
|
|
63
62
|
}
|
|
64
63
|
}
|
|
64
|
+
|
|
65
|
+
console.log(`Disconnected from master server`);
|
|
65
66
|
} catch (e) {
|
|
66
|
-
console.error(
|
|
67
|
+
console.error('Disconnected from master server due to error', e);
|
|
67
68
|
} finally {
|
|
68
|
-
|
|
69
|
+
clearTimeout(resendTimeout);
|
|
69
70
|
}
|
|
70
71
|
})();
|
|
71
72
|
}
|
|
72
73
|
|
|
73
74
|
async getinfo (addr, port) {
|
|
74
75
|
const session = new WebTransport(`https://${addr}:${port}`);
|
|
75
|
-
const writer = session.datagrams.writable.getWriter();
|
|
76
|
-
const reader = session.datagrams.readable.getReader();
|
|
77
76
|
let resendTimeout;
|
|
78
|
-
let
|
|
77
|
+
let res;
|
|
79
78
|
|
|
80
|
-
|
|
79
|
+
session.ready.catch(() => {});
|
|
80
|
+
session.closed.catch(() => {});
|
|
81
81
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
try {
|
|
83
|
+
const sessionClosed = session.closed.then(
|
|
84
|
+
() => ({ done: true, value: null }),
|
|
85
|
+
(err) => { throw err; }
|
|
86
|
+
);
|
|
85
87
|
|
|
86
|
-
|
|
88
|
+
await session.ready;
|
|
87
89
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
const writer = session.datagrams.writable.getWriter();
|
|
91
|
+
const reader = session.datagrams.readable.getReader();
|
|
92
|
+
let begin;
|
|
90
93
|
|
|
91
|
-
|
|
94
|
+
/* send request multiple times until something is read back */
|
|
95
|
+
const send = () => {
|
|
96
|
+
begin = performance.now();
|
|
92
97
|
|
|
93
|
-
|
|
94
|
-
const { done, value } = await reader.read();
|
|
98
|
+
writer.write(this.encode('getinfo')).catch(() => {});
|
|
95
99
|
|
|
96
|
-
|
|
100
|
+
resendTimeout = setTimeout(send, 3000);
|
|
101
|
+
};
|
|
97
102
|
|
|
98
|
-
|
|
99
|
-
throw new Error('getinfo failed, no response received');
|
|
100
|
-
}
|
|
103
|
+
send();
|
|
101
104
|
|
|
102
|
-
|
|
105
|
+
/* read response */
|
|
106
|
+
const { done, value } = await Promise.race([
|
|
107
|
+
reader.read(),
|
|
108
|
+
sessionClosed
|
|
109
|
+
]);
|
|
103
110
|
|
|
104
|
-
|
|
111
|
+
clearTimeout(resendTimeout);
|
|
105
112
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
113
|
+
if (done) {
|
|
114
|
+
throw new Error('stream closed');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
console.log(`${addr}:${port} ---> ${this.pretty(value)}`);
|
|
109
118
|
|
|
110
|
-
|
|
119
|
+
const msg = this.decode(value);
|
|
111
120
|
|
|
112
|
-
|
|
121
|
+
if (!msg || msg.type !== 'infoResponse') {
|
|
122
|
+
throw new Error('invalid response type');
|
|
123
|
+
}
|
|
113
124
|
|
|
114
|
-
|
|
125
|
+
msg.info.ping = Math.min((performance.now() - begin) >>> 0, 999);
|
|
126
|
+
|
|
127
|
+
res = msg.info;
|
|
128
|
+
} catch (e) {
|
|
129
|
+
console.error('getinfo failed', e);
|
|
130
|
+
throw e;
|
|
131
|
+
} finally {
|
|
132
|
+
clearTimeout(resendTimeout);
|
|
133
|
+
|
|
134
|
+
session.close();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return res;
|
|
115
138
|
}
|
|
116
139
|
|
|
117
140
|
async getstatus (addr, port) {
|
|
118
141
|
const session = new WebTransport(`https://${addr}:${port}`);
|
|
119
|
-
const writer = session.datagrams.writable.getWriter();
|
|
120
|
-
const reader = session.datagrams.readable.getReader();
|
|
121
142
|
let resendTimeout;
|
|
122
|
-
let
|
|
143
|
+
let res;
|
|
123
144
|
|
|
124
|
-
|
|
145
|
+
session.ready.catch(() => {});
|
|
146
|
+
session.closed.catch(() => {});
|
|
125
147
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
148
|
+
try {
|
|
149
|
+
const sessionClosed = session.closed.then(
|
|
150
|
+
() => ({ done: true, value: null }),
|
|
151
|
+
(err) => { throw err; }
|
|
152
|
+
);
|
|
129
153
|
|
|
130
|
-
|
|
154
|
+
await session.ready;
|
|
131
155
|
|
|
132
|
-
|
|
133
|
-
|
|
156
|
+
const writer = session.datagrams.writable.getWriter();
|
|
157
|
+
const reader = session.datagrams.readable.getReader();
|
|
158
|
+
let begin;
|
|
134
159
|
|
|
135
|
-
|
|
160
|
+
/* send request multiple times until something is read back */
|
|
161
|
+
const send = () => {
|
|
162
|
+
begin = performance.now();
|
|
136
163
|
|
|
137
|
-
|
|
138
|
-
const { done, value } = await reader.read();
|
|
164
|
+
writer.write(this.encode('getstatus')).catch(() => {});
|
|
139
165
|
|
|
140
|
-
|
|
166
|
+
resendTimeout = setTimeout(send, 3000);
|
|
167
|
+
};
|
|
141
168
|
|
|
142
|
-
|
|
143
|
-
throw new Error('getstatus failed, no response received');
|
|
144
|
-
}
|
|
169
|
+
send();
|
|
145
170
|
|
|
146
|
-
|
|
171
|
+
/* read response */
|
|
172
|
+
const { done, value } = await Promise.race([
|
|
173
|
+
reader.read(),
|
|
174
|
+
sessionClosed
|
|
175
|
+
]);
|
|
147
176
|
|
|
148
|
-
|
|
177
|
+
clearTimeout(resendTimeout);
|
|
149
178
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
179
|
+
if (done) {
|
|
180
|
+
throw new Error('stream closed');
|
|
181
|
+
}
|
|
153
182
|
|
|
154
|
-
|
|
183
|
+
console.log(`${addr}:${port} ---> ${this.pretty(value)}`);
|
|
155
184
|
|
|
156
|
-
|
|
185
|
+
const msg = this.decode(value);
|
|
186
|
+
|
|
187
|
+
if (!msg || msg.type !== 'statusResponse') {
|
|
188
|
+
throw new Error('invalid response type');
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
msg.info.ping = Math.min((performance.now() - begin) >>> 0, 999);
|
|
192
|
+
|
|
193
|
+
res = { info: msg.info, players: msg.players };
|
|
194
|
+
} catch (e) {
|
|
195
|
+
console.error('getstatus failed', e);
|
|
196
|
+
throw e;
|
|
197
|
+
} finally {
|
|
198
|
+
clearTimeout(resendTimeout);
|
|
199
|
+
|
|
200
|
+
session.close();
|
|
201
|
+
}
|
|
157
202
|
|
|
158
|
-
return
|
|
203
|
+
return res;
|
|
159
204
|
}
|
|
160
205
|
}
|
|
161
206
|
|
package/master-server.js
CHANGED
|
@@ -158,11 +158,20 @@ class MasterServer extends MasterBase {
|
|
|
158
158
|
break;
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
+
/* prevent unhandled rejections before main loop */
|
|
162
|
+
session.ready.catch(() => {});
|
|
163
|
+
session.closed.catch(() => {});
|
|
164
|
+
|
|
161
165
|
(async () => {
|
|
162
166
|
try {
|
|
167
|
+
const sessionClosed = session.closed.then(
|
|
168
|
+
() => ({ done: true, value: null }),
|
|
169
|
+
(err) => { throw err; }
|
|
170
|
+
);
|
|
171
|
+
|
|
163
172
|
await session.ready;
|
|
164
173
|
|
|
165
|
-
const writer = session.datagrams.
|
|
174
|
+
const writer = session.datagrams.writable.getWriter();
|
|
166
175
|
const reader = session.datagrams.readable.getReader();
|
|
167
176
|
const [addr, port] = session.peerAddress.split(':');
|
|
168
177
|
let first = true;
|
|
@@ -171,14 +180,17 @@ class MasterServer extends MasterBase {
|
|
|
171
180
|
session.port = port;
|
|
172
181
|
|
|
173
182
|
session.write = (data) => {
|
|
174
|
-
writer.write(data);
|
|
183
|
+
writer.write(data).catch(e => {});
|
|
175
184
|
};
|
|
176
185
|
|
|
177
186
|
while (true) {
|
|
178
|
-
const { done, value } = await
|
|
187
|
+
const { done, value } = await Promise.race([
|
|
188
|
+
reader.read(),
|
|
189
|
+
sessionClosed
|
|
190
|
+
]);
|
|
179
191
|
|
|
180
192
|
if (done) {
|
|
181
|
-
|
|
193
|
+
break;
|
|
182
194
|
}
|
|
183
195
|
|
|
184
196
|
console.log(`${session.addr}:${session.port} ---> ${this.pretty(value)}`);
|
|
@@ -214,10 +226,8 @@ class MasterServer extends MasterBase {
|
|
|
214
226
|
break;
|
|
215
227
|
}
|
|
216
228
|
}
|
|
217
|
-
|
|
218
|
-
console.log(`Client ${session.addr}:${session.port} disconnected`);
|
|
219
229
|
} catch (e) {
|
|
220
|
-
console.error(`Client ${session.addr}:${session.port}
|
|
230
|
+
console.error(`Client ${session.addr}:${session.port} terminated`, e);
|
|
221
231
|
} finally {
|
|
222
232
|
this.#removeClient(session);
|
|
223
233
|
}
|