function _connect()
{
if ($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR) {
return false;
}
$this->bitmap |= NET_SSH2_MASK_CONSTRUCTOR;
$this->curTimeout = $this->timeout;
$this->last_packet = strtok(microtime(), ' ') + strtok('');
// == microtime(true) in PHP5
if (!is_resource($this->fsock)) {
$start = strtok(microtime(), ' ') + strtok('');
// http://php.net/microtime#61838
$this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->curTimeout);
if (!$this->fsock) {
$host = $this->host . ':' . $this->port;
user_error(rtrim("Cannot connect to {$host}. Error {$errno}. {$errstr}"));
return false;
}
$elapsed = strtok(microtime(), ' ') + strtok('') - $start;
$this->curTimeout -= $elapsed;
if ($this->curTimeout <= 0) {
$this->is_timeout = true;
return false;
}
}
/* According to the SSH2 specs,
"The server MAY send other lines of data before sending the version
string. Each line SHOULD be terminated by a Carriage Return and Line
Feed. Such lines MUST NOT begin with "SSH-", and SHOULD be encoded
in ISO-10646 UTF-8 [RFC3629] (language is not specified). Clients
MUST be able to process such lines." */
$temp = '';
$extra = '';
while (!feof($this->fsock) && !preg_match('#^SSH-(\\d\\.\\d+)#', $temp, $matches)) {
if (substr($temp, -2) == "\r\n") {
$extra .= $temp;
$temp = '';
}
if ($this->curTimeout) {
if ($this->curTimeout < 0) {
$this->is_timeout = true;
return false;
}
$read = array($this->fsock);
$write = $except = null;
$start = strtok(microtime(), ' ') + strtok('');
$sec = floor($this->curTimeout);
$usec = 1000000 * ($this->curTimeout - $sec);
// on windows this returns a "Warning: Invalid CRT parameters detected" error
// the !count() is done as a workaround for <https://bugs.php.net/42682>
if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
$this->is_timeout = true;
return false;
}
$elapsed = strtok(microtime(), ' ') + strtok('') - $start;
$this->curTimeout -= $elapsed;
}
$temp .= fgets($this->fsock, 255);
}
if (feof($this->fsock)) {
user_error('Connection closed by server');
return false;
}
$this->identifier = $this->_generate_identifier();
if (defined('NET_SSH2_LOGGING')) {
$this->_append_log('<-', $extra . $temp);
$this->_append_log('->', $this->identifier . "\r\n");
}
$this->server_identifier = trim($temp, "\r\n");
if (strlen($extra)) {
$this->errors[] = utf8_decode($extra);
}
if ($matches[1] != '1.99' && $matches[1] != '2.0') {
user_error("Cannot connect to SSH {$matches['1']} servers");
return false;
}
fputs($this->fsock, $this->identifier . "\r\n");
$response = $this->_get_binary_packet();
if ($response === false) {
user_error('Connection closed by server');
return false;
}
if (ord($response[0]) != NET_SSH2_MSG_KEXINIT) {
user_error('Expected SSH_MSG_KEXINIT');
return false;
}
if (!$this->_key_exchange($response)) {
return false;
}
$this->bitmap |= NET_SSH2_MASK_CONNECTED;
return true;
}