Skip to content

Commit

Permalink
Merge branch 'keepalive-1.0' into 1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
terrafrost committed Dec 17, 2020
2 parents e6abc61 + 0399faa commit 2b5e205
Showing 1 changed file with 85 additions and 29 deletions.
114 changes: 85 additions & 29 deletions phpseclib/Net/SSH2.php
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,14 @@ class Net_SSH2
*/
var $curTimeout;

/**
* Keep Alive Interval
*
* @see self::setKeepAlive()
* @access private
*/
var $keepAlive;

/**
* Real-time log file pointer
*
Expand Down Expand Up @@ -2692,6 +2700,19 @@ function setTimeout($timeout)
$this->timeout = $this->curTimeout = $timeout;
}

/**
* Set Keep Alive
*
* Sends an SSH2_MSG_IGNORE message every x seconds, if x is a positive non-zero number.
*
* @param mixed $timeout
* @access public
*/
function setKeepAlive($interval)
{
$this->keepAlive = $interval;
}

/**
* Get the output from stdError
*
Expand Down Expand Up @@ -3331,6 +3352,54 @@ function _reset_connection($reason)
*/
function _get_binary_packet($skip_channel_filter = false)
{
if ($skip_channel_filter) {
$read = array($this->fsock);
$write = $except = null;

if ($this->curTimeout <= 0) {
if ($this->keepAlive <= 0) {
@stream_select($read, $write, $except, null);
} else {
if (!@stream_select($read, $write, $except, $this->keepAlive) && !count($read)) {
$this->_send_binary_packet(pack('CN', NET_SSH2_MSG_IGNORE, 0));
return $this->_get_binary_packet(true);
}
}
} else {
if ($this->curTimeout < 0) {
$this->is_timeout = true;
return true;
}

$read = array($this->fsock);
$write = $except = null;

$start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838

if ($this->keepAlive > 0 && $this->keepAlive < $this->curTimeout) {
if (!@stream_select($read, $write, $except, $this->keepAlive) && !count($read)) {
$this->_send_binary_packet(pack('CN', NET_SSH2_MSG_IGNORE, 0));
$elapsed = strtok(microtime(), ' ') + strtok('') - $start;
$this->curTimeout-= $elapsed;
return $this->_get_binary_packet(true);
}
$elapsed = strtok(microtime(), ' ') + strtok('') - $start;
$this->curTimeout-= $elapsed;
}

$sec = floor($this->curTimeout);
$usec = 1000000 * ($this->curTimeout - $sec);

// on windows this returns a "Warning: Invalid CRT parameters detected" error
if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
$this->is_timeout = true;
return true;
}
$elapsed = strtok(microtime(), ' ') + strtok('') - $start;
$this->curTimeout-= $elapsed;
}
}

if (!is_resource($this->fsock) || feof($this->fsock)) {
$this->bitmap = 0;
user_error('Connection closed prematurely');
Expand Down Expand Up @@ -3482,9 +3551,19 @@ function _filter($payload, $skip_channel_filter)
// only called when we've already logged in
if (($this->bitmap & NET_SSH2_MASK_CONNECTED) && $this->isAuthenticated()) {
switch (ord($payload[0])) {
case NET_SSH2_MSG_CHANNEL_REQUEST:
if (strlen($payload) == 31) {
extract(unpack('cpacket_type/Nchannel/Nlength', $payload));
if (substr($payload, 9, $length) == 'keepalive@openssh.com' && isset($this->server_channels[$channel])) {
if (ord(substr($payload, 9 + $length))) { // want reply
$this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_SUCCESS, $this->server_channels[$channel]));
}
$payload = $this->_get_binary_packet($skip_channel_filter);
}
}
break;
case NET_SSH2_MSG_CHANNEL_DATA:
case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA:
case NET_SSH2_MSG_CHANNEL_REQUEST:
case NET_SSH2_MSG_CHANNEL_CLOSE:
case NET_SSH2_MSG_CHANNEL_EOF:
if (!$skip_channel_filter && !empty($this->server_channels)) {
Expand Down Expand Up @@ -3682,36 +3761,13 @@ function _get_channel_packet($client_channel, $skip_extended = false)
$response = $this->binary_packet_buffer;
$this->binary_packet_buffer = false;
} else {
$read = array($this->fsock);
$write = $except = null;

if (!$this->curTimeout) {
@stream_select($read, $write, $except, null);
} else {
if ($this->curTimeout < 0) {
$this->is_timeout = true;
return true;
}

$read = array($this->fsock);
$write = $except = null;

$start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
$sec = floor($this->curTimeout);
$usec = 1000000 * ($this->curTimeout - $sec);
// on windows this returns a "Warning: Invalid CRT parameters detected" error
if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
$this->is_timeout = true;
if ($client_channel == NET_SSH2_CHANNEL_EXEC && !$this->request_pty) {
$this->_close_channel($client_channel);
}
return true;
$response = $this->_get_binary_packet(true);
if ($response === true && $this->is_timeout) {
if ($client_channel == NET_SSH2_CHANNEL_EXEC && !$this->request_pty) {
$this->_close_channel($client_channel);
}
$elapsed = strtok(microtime(), ' ') + strtok('') - $start;
$this->curTimeout-= $elapsed;
return true;
}

$response = $this->_get_binary_packet(true);
if ($response === false) {
$this->bitmap = 0;
user_error('Connection closed by server');
Expand Down

0 comments on commit 2b5e205

Please sign in to comment.