UNPKG

@dominiek/ftp-srv

Version:

Modern, extensible FTP Server

134 lines (116 loc) 3.6 kB
const net = require("net"); const tls = require("tls"); const ip = require("ip"); const Promise = require("bluebird"); const Connector = require("./base"); const errors = require("../errors"); const CONNECT_TIMEOUT = 30 * 1000; class Passive extends Connector { constructor(connection) { super(connection); this.type = "passive"; } waitForConnection({ timeout = 5000, delay = 50 } = {}) { if (!this.dataServer) return Promise.reject( new errors.ConnectorError("Passive server not setup") ); const checkSocket = () => { if ( this.dataServer && this.dataServer.listening && this.dataSocket && this.dataSocket.connected ) { return Promise.resolve(this.dataSocket); } return Promise.resolve() .delay(delay) .then(() => checkSocket()); }; return checkSocket().timeout(timeout); } setupServer() { this.closeServer(); return this.server.getNextPasvPort().then((port) => { this.dataSocket = null; let idleServerTimeout; const connectionHandler = (socket) => { /* if (!ip.isEqual(this.connection.commandSocket.remoteAddress, socket.remoteAddress)) { this.log.error({ pasv_connection: socket.remoteAddress, cmd_connection: this.connection.commandSocket.remoteAddress }, 'Connecting addresses do not match'); socket.destroy(); return this.connection.reply(550, 'Remote addresses do not match') .finally(() => this.connection.close()); } */ clearTimeout(idleServerTimeout); this.log.trace( { port, remoteAddress: socket.remoteAddress }, "Passive connection fulfilled." ); this.dataSocket = socket; this.dataSocket.on( "error", (err) => this.server && this.server.emit("client-error", { connection: this.connection, context: "dataSocket", error: err, }) ); this.dataSocket.once("close", () => this.closeServer()); if (!this.connection.secure) { this.dataSocket.connected = true; } }; const serverOptions = Object.assign( {}, this.connection.secure ? this.server.options.tls : {}, { pauseOnConnect: true } ); this.dataServer = (this.connection.secure ? tls : net).createServer( serverOptions, connectionHandler ); this.dataServer.maxConnections = 1; this.dataServer.on( "error", (err) => this.server && this.server.emit("client-error", { connection: this.connection, context: "dataServer", error: err, }) ); this.dataServer.once("close", () => { this.log.trace("Passive server closed"); this.end(); }); if (this.connection.secure) { this.dataServer.on("secureConnection", (socket) => { socket.connected = true; }); } return new Promise((resolve, reject) => { this.dataServer.listen(port, this.server.url.hostname, (err) => { if (err) reject(err); else { idleServerTimeout = setTimeout( () => this.closeServer(), CONNECT_TIMEOUT ); this.log.debug({ port }, "Passive connection listening"); resolve(this.dataServer); } }); }); }); } } module.exports = Passive;