-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest-quakejs-ws.js
More file actions
executable file
·130 lines (104 loc) · 3.07 KB
/
Copy pathtest-quakejs-ws.js
File metadata and controls
executable file
·130 lines (104 loc) · 3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/usr/bin/env node
const WebSocket = require('ws');
const host = process.argv[2] || 'uniquake-dev.dyndns.org';
const port = process.argv[3] || '27961';
console.log(`Connecting to ws://${host}:${port}...`);
// Use the same options as QuakeJS
const ws = new WebSocket(`ws://${host}:${port}`, {
headers: { 'websocket-protocol': ['binary'] }
});
ws.binaryType = 'arraybuffer';
// Helper to format OOB packets
function formatOOB(data) {
const str = '\xff\xff\xff\xff' + data + '\x00';
const buffer = new ArrayBuffer(str.length);
const view = new Uint8Array(buffer);
for (let i = 0; i < str.length; i++) {
view[i] = str.charCodeAt(i);
}
return buffer;
}
// Helper to strip OOB header
function stripOOB(buffer) {
const view = new DataView(buffer);
if (view.getInt32(0) !== -1) {
return null;
}
let str = '';
for (let i = 4; i < buffer.byteLength - 1; i++) {
const c = String.fromCharCode(view.getUint8(i));
str += c;
}
return str;
}
ws.on('open', () => {
console.log('Connected!');
// Send a port identifier first (optional)
const portMsg = new ArrayBuffer(10);
const portView = new Uint8Array(portMsg);
portView[0] = 255; portView[1] = 255; portView[2] = 255; portView[3] = 255;
portView[4] = 'p'.charCodeAt(0);
portView[5] = 'o'.charCodeAt(0);
portView[6] = 'r'.charCodeAt(0);
portView[7] = 't'.charCodeAt(0);
portView[8] = (parseInt(port) >> 8) & 0xff;
portView[9] = parseInt(port) & 0xff;
ws.send(portMsg);
console.log('Sent port identifier');
// Try sending a getinfo request
setTimeout(() => {
const getinfo = formatOOB('getinfo xxx');
ws.send(getinfo);
console.log('Sent getinfo request');
}, 100);
// Try sending a getstatus request
setTimeout(() => {
const getstatus = formatOOB('getstatus');
ws.send(getstatus);
console.log('Sent getstatus request');
}, 200);
});
ws.on('message', (data) => {
console.log('Received message:', data);
// Handle both Buffer and ArrayBuffer
let buffer;
if (data instanceof ArrayBuffer) {
buffer = data;
} else if (Buffer.isBuffer(data)) {
// Convert Node Buffer to ArrayBuffer
buffer = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
} else {
console.log('Unknown data type:', typeof data);
return;
}
const msg = stripOOB(buffer);
if (msg) {
console.log('OOB message:', msg);
} else {
console.log('Non-OOB data:', new Uint8Array(buffer));
}
});
ws.on('error', (err) => {
console.error('WebSocket error:', err);
});
ws.on('close', (code, reason) => {
console.log(`Connection closed: ${code} ${reason}`);
});
// Try more commands
setTimeout(() => {
// Send a connect request
const connect = formatOOB('connect');
ws.send(connect);
console.log('Sent connect request');
}, 300);
setTimeout(() => {
// Send a getchallenge request
const getchallenge = formatOOB('getchallenge');
ws.send(getchallenge);
console.log('Sent getchallenge request');
}, 400);
// Keep the script running
setTimeout(() => {
console.log('Closing connection...');
ws.close();
}, 10000);