title: NodeJS ssh2 fastGet hangs on decompression
body: <p>Using the nodejs ssh2 library by mscdex, I have a sftp "fetch" node script that will list the contents of an ssh server directory, searches for particular files, and then downloads them. When the script gets to the download step where it calls "sftp.fastGet", the callback provided to fastGet is never called.</p>
  
  <p>I've turned on the "DEBUG" setting in the ssh connection option. It seems like the sftp.fastGet is executing, but is hanging on a "decompress" step. This is the output I am getting:</p>
  
  <pre><code>...
  DEBUG: Parser: Verifying MAC
  DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
  DEBUG: Parser: Decompressing
  // hangs here forever (or until timeout)...
  </code></pre>
  
  <p>What is more strange, several packets seem to come over and decompress correctly. Here is the (more verbose) debug:</p>
  
  <pre><code>info: Fetching xxx from /xxx/xxx/xxx to X:\xxx\xxx\xxx
  debug: DEBUG[SFTP]: Outgoing: Writing OPEN
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG: Parser: IN_PACKET
  debug: DEBUG: Parser: Decrypting
  debug: DEBUG: Parser: pktLen:20,padLen:5,remainLen:16
  debug: DEBUG: Parser: IN_PACKETDATA
  debug: DEBUG: Parser: Decrypting
  debug: DEBUG: Parser: HMAC size:20
  debug: DEBUG: Parser: IN_PACKETDATAVERIFY
  debug: DEBUG: Parser: Verifying MAC
  debug: DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
  debug: DEBUG: Parser: Decompressing
  // doesn't seem to hang here
  debug: DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Parser: Response: HANDLE
  debug: DEBUG[SFTP]: Outgoing: Writing FSTAT
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG: Parser: IN_PACKETBEFORE (expecting 8)
  debug: DEBUG: Parser: IN_PACKET
  debug: DEBUG: Parser: Decrypting
  debug: DEBUG: Parser: pktLen:28,padLen:10,remainLen:24
  debug: DEBUG: Parser: IN_PACKETDATA
  debug: DEBUG: Parser: Decrypting
  debug: DEBUG: Parser: HMAC size:20
  debug: DEBUG: Parser: IN_PACKETDATAVERIFY
  debug: DEBUG: Parser: Verifying MAC
  debug: DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
  debug: DEBUG: Parser: Decompressing
  // doesn't seem to hang here
  debug: DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Parser: Response: ATTRS
  debug: DEBUG: Parser: IN_PACKETBEFORE (expecting 8)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG[SFTP]: Outgoing: Writing READ
  debug: DEBUG: Outgoing: Writing CHANNEL_DATA (0)
  debug: DEBUG: Parser: IN_PACKET
  debug: DEBUG: Parser: Decrypting
  debug: DEBUG: Parser: pktLen:2388,padLen:6,remainLen:2384
  debug: DEBUG: Parser: IN_PACKETDATA
  debug: DEBUG: Parser: Decrypting
  debug: DEBUG: Parser: HMAC size:20
  debug: DEBUG: Parser: IN_PACKETDATAVERIFY
  debug: DEBUG: Parser: Verifying MAC
  debug: DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)
  debug: DEBUG: Parser: Decompressing
  // hangs here forever...
  </code></pre>
  
  <p>I cracked open "[my project]\node_modules\ssh2-streams\lib\ssh.js" and found that the "decompress.instance.flush" method callback was not being called every time.</p>
  
  <pre><code>ssh.js line 544: ...
  } else if (instate.status === IN_PACKETDATAAFTER) {
    if (decompress.instance) {
    if (!decomp) {
      debug('DEBUG: Parser: Decompressing');
      decompress.instance.write(instate.payload);
      // this function executes and calls the method below
      decompress.instance.flush(Z_PARTIAL_FLUSH, function(){
        // this callback function is called during the first two iterations,
        // but is not called the last time, when the process hangs
        instate.payload = decompress.instance.read();
        var nextSlice;
        if (i === chlen)
          nextSlice = EMPTY_BUFFER;
        else
          nextSlice = chunk.slice(i);
        self._transform(nextSlice, encoding, callback, true);
      });
      return;
    } else {
    ...
  </code></pre>
  
  <p>... and of course, here is the code I am running</p>
  
  <pre><code>var sshClient = require('ssh2').Client;
  
  var client = new sshClient();
  
  client.on('ready', ()=&gt; {
  
    client.sftp( (sftpErr, sftp) =&gt; {
  
      sftp.readdir(remotepath, (dirErr, files) =&gt; {
  
        var validFiles = files.filter( (file) =&gt; {
          return file.filename.match(regex);
        });  
  
        async.eachSeries(validFiles, (ftpFile, cb) =&gt; {
  
          var remote = remotepath + ftpFile.filename;
          var local = path.join(localpath, ftpFile.filename);
  
  
          console.log('Fetching ' + ftpFile.filename + ' from ' + remote + ' to ' + local);
  
          sftp.fastGet(remote, local, (getErr) =&gt; {
            console.log('Fast Get Complete');
            // this is never called
          });
  
        });
  
      })
  
    });
  
  });
  
  client.connect({
    host: "xxx.xxx.xxx.xxx",
    port: 22,
    username: "someuser",
    password: "somepass",
    debug: console.log,
    algorithms: {
      key: [
        "diffie-hellman-group1-sha1",
      ],
      cipher: [
        "blowfish-cbc",
        "3des-cbc"
      ],
      compress: [
        "zlib"
      ],
      hmac: [
        "hmac-sha1",
        "hmac-md5"
      ]
    }
  });
  </code></pre>