steelbrain / node-ssh

SSH2 with Promises
MIT License
947 stars 94 forks source link

can not add event listener for handshake event to identify negotiated kex #464

Closed aditya81070 closed 1 year ago

aditya81070 commented 1 year ago

Hey , thanks for this awesome promised based SFTP client. As this library provides a wrapper over the native ssh2 library, I feel that some parts are very restricted.

In the current usecase, I want to listen to handshake event as mentioned in the client-events generated by ssh2. I will use the negotiated kex algorithm to decide the cpu limits for next operations.

Currently I am using node-ssh@^6.0.0 which have following type declaration for the SSH class.

declare class SSH {
    constructor();

    connect(givenConfig: SSH.ConfigGiven): Promise<this>;

    requestShell(): Promise<SSH.Shell>;

    requestSFTP(): Promise<SSH.SFTP>;
// ...other methods
}

I checked the lib code for this version and found that the connection is set to null in constructor and then a new ssh2 instance is created whenever connect method is called.

class SSH {
  constructor() {
    this.connection = null;
  }

  connect(givenConfig) {
    const connection = new _ssh.default();
    this.connection = connection;
   // ...remaining code
}
// ...other methods
}

The connect method connects to SFTP server and return the same instance of the class (for chaining most probably).

If I want to add event listener for handshake event then I will need access to this.connection which is created in the connect method but I can only add this once connect method is completed so event listener won't even invoked.

I checked the code for latest version in this repo. The type definitions are improved but still I can't access the underlying connection instance before connect or pass event handlers for handshake event.

Am I missing something here if it is possible with the library? If it is not, which is the best way of getting the data returned in handshake event (without using ssh2 directly which means I have to depend on two libraries)? Thanks

Edit: Just found out that node-ssh@6.x.x. is using ssh2@0.8.2 which didn't have handshake event as it was added in ssh2@1.0.0 as part of rewrite (https://github.com/mscdex/ssh2/issues/935)

steelbrain commented 1 year ago

Hi @aditya81070

Thanks for writing in. For your usecase, you may be able to use the ssh.connection prop as you mentioned to listen for the handshake event.

Here's what it would look like

async function doSomething() {
  const ssh = new NodeSSH()
  const connectionPromise = ssh.connect(...)
  ssh.connection.on('...', ...);
  await connectionPromise
}
doSomething(...)

By deferring the await on connection promise until after the listener is added, you should be able to hook into the handshake and other events

aditya81070 commented 1 year ago

Hey @steelbrain , thanks for the answer. 😂 Nicely used the async nature of javascript. If I am understanding it correctly, you have called the connect promise and put it into event loop and as you are not awaiting the next line will be executed and new event listener will be attached to same connection instance and after that you wait for fulfilment of the already fired promise. As connection creation will take time anyway so this listener will be attached.