Skip to content

Commit c1fc88a

Browse files
committed
Refactor huge try-catch by buffer length checking.
1 parent 8f19e8a commit c1fc88a

File tree

2 files changed

+184
-172
lines changed

2 files changed

+184
-172
lines changed

local.js

+110-102
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,7 @@ var server = net.createServer(function (connection) {
9090
});
9191
const encryptor = new Encryptor(KEY, METHOD);
9292
let stage = 0;
93-
let headerLength = 0;
9493
let cachedPieces = [];
95-
let addrLen = 0;
9694
let ws = null;
9795
let remoteAddr = null;
9896
let remotePort = null;
@@ -115,126 +113,136 @@ var server = net.createServer(function (connection) {
115113
return;
116114
}
117115
if (stage === 1) {
118-
try {
119-
// +----+-----+-------+------+----------+----------+
120-
// |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
121-
// +----+-----+-------+------+----------+----------+
122-
// | 1 | 1 | X'00' | 1 | Variable | 2 |
123-
// +----+-----+-------+------+----------+----------+
116+
// +----+-----+-------+------+----------+----------+
117+
// |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
118+
// +----+-----+-------+------+----------+----------+
119+
// | 1 | 1 | X'00' | 1 | Variable | 2 |
120+
// +----+-----+-------+------+----------+----------+
124121

125-
//cmd and addrtype
126-
const cmd = data[1];
127-
const addrtype = data[3];
128-
if (cmd !== 1) {
129-
console.log('unsupported cmd:', cmd);
130-
const reply = Buffer.from('\u0005\u0007\u0000\u0001', 'binary');
131-
connection.end(reply);
122+
let headerLength = 5;
123+
124+
if (data.length < headerLength) {
125+
connection.end();
126+
return;
127+
}
128+
const cmd = data[1];
129+
const addrtype = data[3];
130+
if (cmd !== 1) {
131+
console.log('unsupported cmd:', cmd);
132+
const reply = Buffer.from('\u0005\u0007\u0000\u0001', 'binary');
133+
connection.end(reply);
134+
return;
135+
}
136+
if (![1, 3, 4].includes(addrtype)) {
137+
console.log('unsupported addrtype:', addrtype);
138+
connection.end();
139+
return;
140+
}
141+
addrToSend = data.slice(3, 4).toString('binary');
142+
143+
// read address and port
144+
if (addrtype === 1) {
145+
// ipv4
146+
headerLength = 4 + 4 + 2;
147+
if (data.length < headerLength) {
148+
connection.end();
132149
return;
133150
}
134-
if (addrtype === 3) {
135-
addrLen = data[4];
136-
} else if (addrtype !== 1 && addrtype !== 4) {
137-
console.log('unsupported addrtype:', addrtype);
151+
remoteAddr = inetNtoa(4, data.slice(4, 8));
152+
addrToSend += data.slice(4, 10).toString('binary');
153+
remotePort = data.readUInt16BE(8);
154+
} else if (addrtype === 4) {
155+
// ipv6
156+
headerLength = 4 + 16 + 2;
157+
if (data.length < headerLength) {
138158
connection.end();
139159
return;
140160
}
141-
addrToSend = data.slice(3, 4).toString('binary');
142-
// read address and port
143-
if (addrtype === 1) {
144-
// ipv4
145-
remoteAddr = inetNtoa(4, data.slice(4, 8));
146-
addrToSend += data.slice(4, 10).toString('binary');
147-
remotePort = data.readUInt16BE(8);
148-
headerLength = 10;
149-
} else if (addrtype === 4) {
150-
// ipv6
151-
remoteAddr = inetNtoa(6, data.slice(4, 20));
152-
addrToSend += data.slice(4, 22).toString('binary');
153-
remotePort = data.readUInt16BE(20);
154-
headerLength = 22;
155-
} else {
156-
remoteAddr = data.slice(5, 5 + addrLen).toString('binary');
157-
addrToSend += data.slice(4, 5 + addrLen + 2).toString('binary');
158-
remotePort = data.readUInt16BE(5 + addrLen);
159-
headerLength = 5 + addrLen + 2;
161+
remoteAddr = inetNtoa(6, data.slice(4, 20));
162+
addrToSend += data.slice(4, 22).toString('binary');
163+
remotePort = data.readUInt16BE(20);
164+
} else {
165+
const addrLen = data[4];
166+
headerLength = 5 + addrLen + 2;
167+
if (data.length < headerLength) {
168+
connection.end();
169+
return;
160170
}
161-
let buf = Buffer.alloc(10);
162-
buf.write('\u0005\u0000\u0000\u0001', 0, 4, 'binary');
163-
buf.write('\u0000\u0000\u0000\u0000', 4, 4, 'binary');
164-
buf.writeUInt16BE(remotePort, 8);
165-
connection.write(buf);
166-
// connect to remote server
167-
// ws = new WebSocket aServer, protocol: "binary"
171+
remoteAddr = data.slice(5, 5 + addrLen).toString('binary');
172+
addrToSend += data.slice(4, 5 + addrLen + 2).toString('binary');
173+
remotePort = data.readUInt16BE(5 + addrLen);
174+
}
175+
let buf = Buffer.alloc(10);
176+
buf.write('\u0005\u0000\u0000\u0001', 0, 4, 'binary');
177+
buf.write('\u0000\u0000\u0000\u0000', 4, 4, 'binary');
178+
buf.writeUInt16BE(remotePort, 8);
179+
connection.write(buf);
180+
// connect to remote server
181+
// ws = new WebSocket aServer, protocol: "binary"
168182

169-
if (HTTPPROXY) {
170-
// WebSocket endpoint for the proxy to connect to
171-
const endpoint = aServer;
172-
const parsed = url.parse(endpoint);
173-
//console.log('attempting to connect to WebSocket %j', endpoint);
183+
if (HTTPPROXY) {
184+
// WebSocket endpoint for the proxy to connect to
185+
const endpoint = aServer;
186+
const parsed = url.parse(endpoint);
187+
//console.log('attempting to connect to WebSocket %j', endpoint);
174188

175-
// create an instance of the `HttpsProxyAgent` class with the proxy server information
176-
const opts = url.parse(HTTPPROXY);
189+
// create an instance of the `HttpsProxyAgent` class with the proxy server information
190+
const opts = url.parse(HTTPPROXY);
177191

178-
// IMPORTANT! Set the `secureEndpoint` option to `false` when connecting
179-
// over "ws://", but `true` when connecting over "wss://"
180-
opts.secureEndpoint = parsed.protocol
181-
? parsed.protocol == 'wss:'
182-
: false;
192+
// IMPORTANT! Set the `secureEndpoint` option to `false` when connecting
193+
// over "ws://", but `true` when connecting over "wss://"
194+
opts.secureEndpoint = parsed.protocol
195+
? parsed.protocol == 'wss:'
196+
: false;
183197

184-
const agent = new HttpsProxyAgent(opts);
198+
const agent = new HttpsProxyAgent(opts);
185199

186-
ws = new WebSocket(aServer, {
187-
protocol: 'binary',
188-
agent,
189-
});
190-
} else {
191-
ws = new WebSocket(aServer, {
192-
protocol: 'binary',
193-
});
194-
}
195-
196-
ws.on('open', function () {
197-
console.log(`connecting ${remoteAddr} via ${aServer}`);
198-
let addrToSendBuf = Buffer.from(addrToSend, 'binary');
199-
addrToSendBuf = encryptor.encrypt(addrToSendBuf);
200-
ws.send(addrToSendBuf, {binary: true});
201-
ws.send(encryptor.encrypt(Buffer.concat(cachedPieces)), {
202-
binary: true,
203-
});
204-
cachedPieces = null; // save memory
205-
stage = 5;
200+
ws = new WebSocket(aServer, {
201+
protocol: 'binary',
202+
agent,
206203
});
207-
208-
ws.on('message', function (data, flags) {
209-
data = encryptor.decrypt(data);
210-
connection.write(data);
204+
} else {
205+
ws = new WebSocket(aServer, {
206+
protocol: 'binary',
211207
});
208+
}
212209

213-
ws.on('close', function () {
214-
console.log('remote disconnected');
215-
connection.destroy();
210+
ws.on('open', function () {
211+
console.log(`connecting ${remoteAddr} via ${aServer}`);
212+
let addrToSendBuf = Buffer.from(addrToSend, 'binary');
213+
addrToSendBuf = encryptor.encrypt(addrToSendBuf);
214+
ws.send(addrToSendBuf, {binary: true});
215+
ws.send(encryptor.encrypt(Buffer.concat(cachedPieces)), {
216+
binary: true,
216217
});
218+
cachedPieces = null; // save memory
219+
stage = 5;
220+
});
217221

218-
ws.on('error', function (e) {
219-
console.log(`remote ${remoteAddr}:${remotePort} error: ${e}`);
220-
connection.destroy();
221-
server.getConnections(function (err, count) {
222-
console.log('concurrent connections:', count);
223-
});
224-
});
222+
ws.on('message', function (data, flags) {
223+
data = encryptor.decrypt(data);
224+
connection.write(data);
225+
});
225226

226-
if (data.length > headerLength) {
227-
let buf = Buffer.alloc(data.length - headerLength);
228-
data.copy(buf, 0, headerLength);
229-
cachedPieces.push(buf);
230-
}
231-
stage = 4;
232-
} catch (error) {
233-
// may encounter index out of range
234-
const e = error;
235-
console.log(e);
227+
ws.on('close', function () {
228+
console.log('remote disconnected');
236229
connection.destroy();
230+
});
231+
232+
ws.on('error', function (e) {
233+
console.log(`remote ${remoteAddr}:${remotePort} error: ${e}`);
234+
connection.destroy();
235+
server.getConnections(function (err, count) {
236+
console.log('concurrent connections:', count);
237+
});
238+
});
239+
240+
if (data.length > headerLength) {
241+
let buf = Buffer.alloc(data.length - headerLength);
242+
data.copy(buf, 0, headerLength);
243+
cachedPieces.push(buf);
237244
}
245+
stage = 4;
238246
} else if (stage === 4) {
239247
// remote server not connected
240248
// cache received buffers

0 commit comments

Comments
 (0)