      1 var net = require("net"),
      2     crypto = require("crypto"),
      3     tlslib = require("tls");
      4
      5 /**
      6  * @namespace Mockup module
      7  * @name mockup
      8  */
      9 module.exports = runClientMockup;
     10
     11 /**
     12  * <p>Runs a batch of commands against a server</p>
     13  *
     14  * <pre>
     15  * var cmds = ["EHLO FOOBAR", "STARTTLS", "QUIT"];
     16  * runClientMockup(25, "mail.hot.ee", cmds, function(resp){
     17  *     console.log("Final:", resp.toString("utf-8").trim());
     18  * });
     19  * </pre>
     20  *
     21  * @memberOf mockup
     22  * @param {Number} port Port number
     23  * @param {String} host Hostname to connect to
     24  * @param {Array} commands Command list to be sent to server
     25  * @param {Function} callback Callback function to run on completion,
     26  *        has the last response from the server as a param
     27  * @param {Boolean} [debug] if set to true log all input/output
     28  */
     29 function runClientMockup(port, host, commands, callback, debug){
     30     host = host || "localhost";
     31     port = port || 25;
     32     commands = Array.isArray(commands) ? commands : [];
     33
     34     var command, ignore_data = false, sslcontext, pair;
     35
     36     var socket = net.connect(port, host, function(){
     37         socket.on("data", function(chunk){
     38             if(ignore_data)return;
     39
     40             if(debug){
     41                 console.log("S: "+chunk.toString("utf-8").trim());
     42             }
     43
     44             if(!commands.length){
     45                 socket.end();
     46                 if(typeof callback == "function"){
     47                     callback(chunk);
     48                 }
     49                 return;
     50             }
     51
     52             if(["STARTTLS", "STLS"].indexOf((command || "").trim().toUpperCase())>=0){
     53                 ignore_data = true;
     54                 if(debug){
     55                     console.log("Initiated TLS connection");
     56                 }
     57                 sslcontext = crypto.createCredentials();
     58                 pair = tlslib.createSecurePair(sslcontext, false);
     59
     60                 pair.encrypted.pipe(socket);
     61                 socket.pipe(pair.encrypted);
     62                 pair.fd = socket.fd;
     63
     64                 pair.on("secure", function(){
     65                     if(debug){
     66                         console.log("TLS connection secured");
     67                     }
     68                     command = commands.shift();
     69                     if(debug){
     70                         console.log("C: "+command);
     71                     }
     72                     pair.cleartext.write(command+"\r\n");
     73
     74                     pair.cleartext.on("data", function(chunk){
     75                         if(debug){
     76                             console.log("S: "+chunk.toString("utf-8").trim());
     77                         }
     78
     79                         if(!commands.length){
     80                             pair.cleartext.end();
     81                             if(typeof callback == "function"){
     82                                 callback(chunk);
     83                             }
     84                             return;
     85                         }
     86                         command = commands.shift();
     87                         pair.cleartext.write(command+"\r\n");
     88                         if(debug){
     89                             console.log("C: "+command);
     90                         }
     91                     });
     92                 });
     93             }else{
     94                 command = commands.shift();
     95                 socket.write(command+"\r\n");
     96                 if(debug){
     97                     console.log("C: "+command);
     98                 }
     99             }
    100         });
    101     });
    102
    103 }