2017-03-06 05:45:50 +08:00
|
|
|
/*eslint no-console: 0 */
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
let net = require('net');
|
|
|
|
let tls = require('tls');
|
|
|
|
|
|
|
|
module.exports = runClientMockup;
|
|
|
|
|
|
|
|
function runClientMockup(options, callback) {
|
|
|
|
options = options || {};
|
|
|
|
|
|
|
|
let host = options.host || 'localhost';
|
|
|
|
let port = options.port || 25;
|
|
|
|
let commands = [].concat(options.commands || []);
|
|
|
|
let debug = options.debug;
|
|
|
|
|
|
|
|
let ignore_data = false;
|
|
|
|
let responses = [];
|
|
|
|
let command = '';
|
|
|
|
let callbackSent = false;
|
|
|
|
let delay;
|
|
|
|
|
2017-12-13 16:33:13 +08:00
|
|
|
let socket = (options.secure ? tls : net).connect(
|
|
|
|
{
|
|
|
|
rejectUnauthorized: false,
|
|
|
|
port,
|
|
|
|
host
|
|
|
|
},
|
|
|
|
() => {
|
|
|
|
socket.on('close', () => {
|
|
|
|
if (callbackSent) {
|
2017-03-06 05:45:50 +08:00
|
|
|
return;
|
|
|
|
}
|
2017-12-13 16:33:13 +08:00
|
|
|
callbackSent = true;
|
|
|
|
if (typeof callback === 'function') {
|
|
|
|
return callback(Buffer.concat(responses));
|
|
|
|
}
|
|
|
|
});
|
2017-03-06 05:45:50 +08:00
|
|
|
|
2017-12-13 16:33:13 +08:00
|
|
|
let onData = function(chunk) {
|
|
|
|
if (ignore_data) {
|
|
|
|
return;
|
2017-03-06 05:45:50 +08:00
|
|
|
}
|
|
|
|
|
2017-12-13 16:33:13 +08:00
|
|
|
responses.push(chunk);
|
|
|
|
if (debug) {
|
|
|
|
console.log('S: ' + chunk.toString('binary').trim());
|
|
|
|
}
|
2017-03-06 05:45:50 +08:00
|
|
|
|
2017-12-13 16:33:13 +08:00
|
|
|
if (!commands.length) {
|
|
|
|
return;
|
|
|
|
}
|
2017-03-06 05:45:50 +08:00
|
|
|
|
2017-12-13 16:33:13 +08:00
|
|
|
if (typeof command === 'string' && command.match(/^[a-z0-9]+ STARTTLS$/i)) {
|
|
|
|
// wait until server sends response to the STARTTLS command
|
|
|
|
if (!/STARTTLS completed/.test(Buffer.concat(responses).toString())) {
|
|
|
|
return;
|
2017-03-06 05:45:50 +08:00
|
|
|
}
|
|
|
|
|
2017-12-13 16:33:13 +08:00
|
|
|
ignore_data = true;
|
2017-03-06 05:45:50 +08:00
|
|
|
if (debug) {
|
2017-12-13 16:33:13 +08:00
|
|
|
console.log('Initiated TLS connection');
|
2017-03-06 05:45:50 +08:00
|
|
|
}
|
|
|
|
|
2017-12-13 16:33:13 +08:00
|
|
|
socket.removeAllListeners('data');
|
|
|
|
let secureSocket = tls.connect(
|
|
|
|
{
|
|
|
|
rejectUnauthorized: false,
|
|
|
|
socket,
|
|
|
|
host
|
|
|
|
},
|
|
|
|
() => {
|
|
|
|
ignore_data = false;
|
2017-03-06 05:45:50 +08:00
|
|
|
|
2017-12-13 16:33:13 +08:00
|
|
|
socket = secureSocket;
|
|
|
|
|
|
|
|
if (debug) {
|
|
|
|
console.log('TLS connection secured');
|
2017-03-06 05:45:50 +08:00
|
|
|
}
|
|
|
|
|
2017-12-13 16:33:13 +08:00
|
|
|
secureSocket.on('data', onData);
|
|
|
|
|
|
|
|
secureSocket.on('close', () => {
|
|
|
|
if (callbackSent) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
callbackSent = true;
|
|
|
|
if (typeof callback === 'function') {
|
|
|
|
return callback(Buffer.concat(responses));
|
|
|
|
}
|
|
|
|
});
|
2017-03-06 05:45:50 +08:00
|
|
|
|
2017-12-13 16:33:13 +08:00
|
|
|
command = commands.shift();
|
2017-03-06 05:45:50 +08:00
|
|
|
if (debug) {
|
2017-12-13 16:33:13 +08:00
|
|
|
console.log('(Secure) C: ' + command);
|
2017-03-06 05:45:50 +08:00
|
|
|
}
|
2017-12-13 16:33:13 +08:00
|
|
|
secureSocket.write(command + '\r\n');
|
2017-03-06 05:45:50 +08:00
|
|
|
}
|
2017-12-13 16:33:13 +08:00
|
|
|
);
|
|
|
|
|
|
|
|
secureSocket.on('error', err => {
|
|
|
|
console.log('SECURE ERR');
|
|
|
|
console.log(err.stack);
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
if (!/\r?\n$/.test(chunk.toString('binary'))) {
|
|
|
|
return;
|
2017-03-06 05:45:50 +08:00
|
|
|
}
|
2017-12-13 16:33:13 +08:00
|
|
|
// only go forward with the next command if the last data ends with a newline
|
|
|
|
// and there is no activity in the socket for 10ms
|
|
|
|
let processCommand = () => {
|
|
|
|
clearTimeout(delay);
|
|
|
|
delay = setTimeout(() => {
|
|
|
|
command = commands.shift();
|
|
|
|
if (command === 'SLEEP') {
|
|
|
|
return setTimeout(processCommand, 1000);
|
|
|
|
}
|
2017-03-06 05:45:50 +08:00
|
|
|
|
2017-12-13 16:33:13 +08:00
|
|
|
if (Array.isArray(command)) {
|
|
|
|
let i = 0;
|
|
|
|
let send = function() {
|
|
|
|
if (i >= command.length) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let part = command[i++];
|
|
|
|
|
|
|
|
socket.write(new Buffer(part + (i >= command.length ? '\r\n' : ''), 'binary'));
|
|
|
|
if (debug) {
|
|
|
|
console.log('C: ' + part);
|
|
|
|
}
|
|
|
|
setTimeout(send, 10);
|
|
|
|
};
|
|
|
|
|
|
|
|
send();
|
|
|
|
} else {
|
|
|
|
socket.write(new Buffer(command + '\r\n', 'binary'));
|
|
|
|
if (debug) {
|
|
|
|
console.log('C: ' + command);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}, 10);
|
|
|
|
};
|
|
|
|
processCommand();
|
|
|
|
}
|
|
|
|
};
|
2017-03-06 05:45:50 +08:00
|
|
|
|
2017-12-13 16:33:13 +08:00
|
|
|
socket.on('data', onData);
|
|
|
|
}
|
|
|
|
);
|
2017-03-06 05:45:50 +08:00
|
|
|
}
|