Error con ssh2 en Node-Webkit

nodewebkitPongamos que quieres desarrollar rápidamente una aplicación cliente-servidor en node-webkit, y que precisamente por la parte de “rápidamente” quieres centrarte en el cliente sin liarte con la comunicación con el servidor.

Una opción sencilla es usar ssh, ejecutando de forma remota en el servidor lo que necesitemos y capturando y parseando las respuestas.

Además querremos que nuestro cliente sea multiplataforma, así que buscando librerías de ssh en javascript encontraremos el módulo ssh2 de npm. Todo perfecto, estás a cinco minutos de tecleo de tener tu aplicación funcionando…

…Y entonces resulta que la conexión falla 4 de cada 5 veces sin tener ni idea de por qué.

El error que obtendrás seguramente sea algo como esto:

Uncaught node.js Error 
Error: Initialization failed
at new DiffieHellman (crypto.js:438:21)
at Object.DiffieHellman (crypto.js:431:12)
at onKEXDH_GEX_GROUP (~/code/node-webkit/testproject/node_modules/ssh2/lib/Connection.js:1628:22)
at Parser.eval (~/code/node-webkit/testproject/node_modules/ssh2/lib/Connection.js:117:5)
at Parser.EventEmitter.emit (events.js:101:17)
at Parser.parsePacket (~/code/node-webkit/testproject/node_modules/ssh2/lib/Parser.js:459:12)
at Parser.execute (~code/node-webkit/testproject/node_modules/ssh2/lib/Parser.js:249:14)
at Socket.eval (~/code/node-webkit/testproject/node_modules/ssh2/lib/Connection.js:506:18)
at Socket.EventEmitter.emit (events.js:98:17)
at readableAddChunk (_stream_readable.js:156:16)

Lo que te deja algo bloqueado es que el error está en la librería crypto.js de node.js, que viene incluido en node-webkit y no es algo a lo que puedas ponerte a meter mano fácilmente.

La culpa del error la tiene la versión 11.x de node.js que incluye la versión 9.x de node-webkit, y de momento la única solución es usar node-webkit 8.x en tu proyecto.

Para el desarrollo tendrás que descargar la última versión de la rama 8.x e “instalarla” de la misma forma que hiciste con la 9.x, de forma que al hacer el nw ./ se esté ejecutando la versión 8 y no la 9.

Para el build, basta que especifiques en el Gruntfile.js la versión específica de node-webkit que quieres usar:

module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('src/package.json'),
nodewebkit: {
options: {
build_dir: './dist',
// specifiy what to build
mac: true,
win: true,
linux32: true,
linux64: true,
version: '0.8.6'
},
src: './src/**/*'
},
});

grunt.loadNpmTasks('grunt-node-webkit-builder');

grunt.registerTask('default', ['nodewebkit']);
};

No es una solución perfecta, en la aplicación en la que me encontré con este problema estaba usando algunos componentes de bootstrap, y por ejemplo los tooltips no hacían el fadeout completo si no que quedaban ligeramente visibles al apartar el ratón del elemento.

Sin saber a ciencia cierta sospecho que la razón de esto sea que en la 8.x se esté usando el V8 de node.js mientras que en 9.x se usa el V8 de Chromium, siendo éste último más actual… aunque también puede que sea sólo por la versión de Chromium en la que está basada cada versión de node-webkit.

De todas formas al menos el SSH funciona perfectamente, que es algo. Supongo que en la próxima release de node-webkit con node.js versión 12 (¿node-webkit 9.3? no se) tal vez se solucionará todo esto.