diff --git a/phpseclib/Net/SSH2.php b/phpseclib/Net/SSH2.php index 6f396974..dc78db8d 100644 --- a/phpseclib/Net/SSH2.php +++ b/phpseclib/Net/SSH2.php @@ -3344,11 +3344,38 @@ class SSH2 /** * Is the connection still active? * + * $level has 3x possible values: + * 0 (default): phpseclib takes a passive approach to see if the connection is still active by calling feof() + * on the socket + * 1: phpseclib takes an active approach to see if the connection is still active by sending an SSH_MSG_IGNORE + * packet that doesn't require a response + * 2: phpseclib takes an active approach to see if the connection is still active by sending an SSH_MSG_CHANNEL_OPEN + * packet and imediately trying to close that channel. some routers, in particular, however, will only let you + * open one channel, so this approach could yield false positives + * + * @param int $level * @return bool */ - public function isConnected() + public function isConnected($level = 0) { - return ($this->bitmap & self::MASK_CONNECTED) && is_resource($this->fsock) && !feof($this->fsock); + if (!is_int($level) || $level < 0 || $level > 2) { + throw new \InvalidArgumentException('$level must be 0, 1 or 2'); + } + + if ($level == 0) { + return ($this->bitmap & self::MASK_CONNECTED) && is_resource($this->fsock) && !feof($this->fsock); + } + try { + if ($level == 1) { + $this->send_binary_packet(pack('CN', NET_SSH2_MSG_IGNORE, 0)); + } else { + $this->openChannel(self::CHANNEL_KEEP_ALIVE); + $this->close_channel(self::CHANNEL_KEEP_ALIVE); + } + return true; + } catch (\Exception $e) { + return false; + } } /**