Example #1
0
 private function _parseBlockData(ProtocolReply $reply, $startDelimiter, $endDelimter)
 {
     $reply->next();
     $line = $reply->current();
     if ($line != $startDelimiter) {
         throw new ProtocolError('Expected line beginning with "' . $startDelimiter . '"');
     }
     $key = $line . "\n";
     do {
         $reply->next();
         $line = $reply->current();
         $key .= $line . "\n";
     } while ($line && $line != $endDelimter);
     return $key;
 }
Example #2
0
 /**
  * Read a complete reply from the controller.
  *
  * This method will process asynchronous events, call the user callback for
  * async events (if any) and then continue to attempt to read a reply from
  * the controller if data is available.
  *
  * This method blocks if there is nothing to be read from the controller.
  *
  * @param $cmd  The name of the previous command sent to the controller
  * @return \Dapphp\TorUtils\ProtocolReply ProtocolReply object containing the response from the controller
  */
 public function readReply($cmd = null)
 {
     $reply = new ProtocolReply($cmd);
     $first = true;
     while (true) {
         $data = $this->_recvData();
         if ($data === false) {
             break;
         }
         if ($this->_isEventReplyLine($data)) {
             // TODO: invoke a callback or process the event and store it somewhere
             if ($first) {
                 $first = false;
                 $evreply = new ProtocolReply();
             }
             $evreply->appendReplyLine($data);
         } else {
             if (trim($data) == '.') {
                 $end = $this->_recvData();
                 if (!$this->_isEndReplyLine($end)) {
                     throw new ProtocolError('Last read "." line - expected EndReplyLine but got "' . trim($end) . '"');
                 }
                 if (!isset($evreply)) {
                     break;
                 } else {
                     $data = $end;
                     // run code at the end of the loop to process evreply
                 }
             } else {
                 if (isset($evreply)) {
                     $evreply->appendReplyLine($data);
                 } else {
                     $reply->appendReplyLine($data);
                 }
             }
         }
         if ($this->_isEndReplyLine($data)) {
             if (isset($evreply)) {
                 $this->_asyncEventHandler($evreply);
                 unset($evreply);
                 $first = true;
             } else {
                 break;
             }
         }
     }
     return $reply;
 }
Example #3
0
 /**
  * Pick a random dir authority to query and perform the HTTP request for directory info
  *
  * @param string $uri Uri to request
  * @param string $directoryServer IP and port of the directory to query
  * @throws \Exception No authorities responded
  * @return \Dapphp\TorUtils\ProtocolReply The reply from the directory authority
  */
 private function _request($uri, $directoryServer = null)
 {
     reset($this->_serverList);
     do {
         // pick a server from the list, it is randomized in __construct
         $server = $this->getNextServer();
         if ($server === false) {
             throw new \Exception('No more directory servers available to query');
         }
         list($host, $port) = @explode(':', $server);
         if (!$port) {
             $port = 80;
         }
         $fp = fsockopen($host, $port, $errno, $errstr, $this->_connectTimeout);
         if (!$fp) {
             continue;
         }
         $request = $this->_getHttpRequest('GET', $host, $uri);
         fwrite($fp, $request);
         $response = '';
         while (!feof($fp)) {
             $response .= fgets($fp);
         }
         fclose($fp);
         list($headers, $body) = explode("\r\n\r\n", $response, 2);
         $headers = $this->_parseHttpResponseHeaders($headers);
         if ($headers['status_code'] !== '200') {
             throw new \Exception(sprintf('Directory returned a negative response code to request.  %s %s', $headers['status_code'], $headers['message']));
         }
         $encoding = isset($headers['headers']['content-encoding']) ? $headers['headers']['content-encoding'] : null;
         if ($encoding == 'deflate') {
             if (!function_exists('gzuncompress')) {
                 throw new \Exception('Directory response was gzip compressed but PHP does not have zlib support enabled');
             }
             $body = gzuncompress($body);
             if ($body === false) {
                 throw new \Exception('Failed to inflate response data');
             }
         } else {
             if ($encoding == 'identity') {
                 // nothing to do
             } else {
                 throw new \Exception('Directory sent response in an unknown encoding: ' . $encoding);
             }
         }
         break;
     } while (true);
     $reply = new ProtocolReply();
     $reply->appendReplyLine(sprintf('%s %s', $headers['status_code'], $headers['message']));
     $reply->appendReplyLines(explode("\n", $body));
     return $reply;
 }