示例#1
0
 /**
  * Connects to the remote server
  *
  * @return   bool    whether the connection can be persistent
  * @throws   HTTP_Request2_Exception
  */
 protected function connect()
 {
     $secure = 0 == strcasecmp($this->request->getUrl()->getScheme(), 'https');
     $tunnel = HTTP_Request2::METHOD_CONNECT == $this->request->getMethod();
     $headers = $this->request->getHeaders();
     $reqHost = $this->request->getUrl()->getHost();
     if (!($reqPort = $this->request->getUrl()->getPort())) {
         $reqPort = $secure ? 443 : 80;
     }
     $httpProxy = $socksProxy = false;
     if (!($host = $this->request->getConfig('proxy_host'))) {
         $host = $reqHost;
         $port = $reqPort;
     } else {
         if (!($port = $this->request->getConfig('proxy_port'))) {
             throw new HTTP_Request2_LogicException('Proxy port not provided', HTTP_Request2_Exception::MISSING_VALUE);
         }
         if ('http' == ($type = $this->request->getConfig('proxy_type'))) {
             $httpProxy = true;
         } elseif ('socks5' == $type) {
             $socksProxy = true;
         } else {
             throw new HTTP_Request2_NotImplementedException("Proxy type '{$type}' is not supported");
         }
     }
     if ($tunnel && !$httpProxy) {
         throw new HTTP_Request2_LogicException("Trying to perform CONNECT request without proxy", HTTP_Request2_Exception::MISSING_VALUE);
     }
     if ($secure && !in_array('ssl', stream_get_transports())) {
         throw new HTTP_Request2_LogicException('Need OpenSSL support for https:// requests', HTTP_Request2_Exception::MISCONFIGURATION);
     }
     // RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive
     // connection token to a proxy server...
     if ($httpProxy && !$secure && !empty($headers['connection']) && 'Keep-Alive' == $headers['connection']) {
         $this->request->setHeader('connection');
     }
     $keepAlive = '1.1' == $this->request->getConfig('protocol_version') && empty($headers['connection']) || !empty($headers['connection']) && 'Keep-Alive' == $headers['connection'];
     $options = array();
     if ($secure || $tunnel) {
         foreach ($this->request->getConfig() as $name => $value) {
             if ('ssl_' == substr($name, 0, 4) && null !== $value) {
                 if ('ssl_verify_host' == $name) {
                     if ($value) {
                         $options['CN_match'] = $reqHost;
                     }
                 } else {
                     $options[substr($name, 4)] = $value;
                 }
             }
         }
         ksort($options);
     }
     // Use global request timeout if given, see feature requests #5735, #8964
     if ($timeout = $this->request->getConfig('timeout')) {
         $deadline = time() + $timeout;
     } else {
         $deadline = null;
     }
     // Changing SSL context options after connection is established does *not*
     // work, we need a new connection if options change
     $remote = (!$secure || $httpProxy || $socksProxy ? 'tcp://' : 'ssl://') . $host . ':' . $port;
     $socketKey = $remote . ($secure && $httpProxy || $socksProxy ? "->{$reqHost}:{$reqPort}" : '') . (empty($options) ? '' : ':' . serialize($options));
     unset($this->socket);
     // We use persistent connections and have a connected socket?
     // Ensure that the socket is still connected, see bug #16149
     if ($keepAlive && !empty(self::$sockets[$socketKey]) && !self::$sockets[$socketKey]->eof()) {
         $this->socket =& self::$sockets[$socketKey];
     } else {
         if ($socksProxy) {
             require_once 'HTTP/Request2/SOCKS5.php';
             $this->socket = new HTTP_Request2_SOCKS5($remote, $this->request->getConfig('connect_timeout'), $options, $this->request->getConfig('proxy_user'), $this->request->getConfig('proxy_password'));
             // handle request timeouts ASAP
             $this->socket->setDeadline($deadline, $this->request->getConfig('timeout'));
             $this->socket->connect($reqHost, $reqPort);
             if (!$secure) {
                 $conninfo = "tcp://{$reqHost}:{$reqPort} via {$remote}";
             } else {
                 $this->socket->enableCrypto();
                 $conninfo = "ssl://{$reqHost}:{$reqPort} via {$remote}";
             }
         } elseif ($secure && $httpProxy && !$tunnel) {
             $this->establishTunnel();
             $conninfo = "ssl://{$reqHost}:{$reqPort} via {$remote}";
         } else {
             $this->socket = new HTTP_Request2_SocketWrapper($remote, $this->request->getConfig('connect_timeout'), $options);
         }
         $this->request->setLastEvent('connect', empty($conninfo) ? $remote : $conninfo);
         self::$sockets[$socketKey] =& $this->socket;
     }
     $this->socket->setDeadline($deadline, $this->request->getConfig('timeout'));
     return $keepAlive;
 }