Verzeichnisstruktur phpBB-3.3.15


Veröffentlicht
28.08.2024

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

CurlMultiHandler.php

Zuletzt modifiziert: 02.04.2025, 15:03 - Dateigröße: 6.26 KiB


001  <?php
002  namespace GuzzleHttp\Handler;
003   
004  use GuzzleHttp\Promise as P;
005  use GuzzleHttp\Promise\Promise;
006  use GuzzleHttp\Utils;
007  use Psr\Http\Message\RequestInterface;
008   
009  /**
010   * Returns an asynchronous response using curl_multi_* functions.
011   *
012   * When using the CurlMultiHandler, custom curl options can be specified as an
013   * associative array of curl option constants mapping to values in the
014   * **curl** key of the provided request options.
015   *
016   * @property resource $_mh Internal use only. Lazy loaded multi-handle.
017   */
018  class CurlMultiHandler
019  {
020      /** @var CurlFactoryInterface */
021      private $factory;
022      private $selectTimeout;
023      private $active;
024      private $handles = [];
025      private $delays = [];
026      private $options = [];
027   
028      /**
029       * This handler accepts the following options:
030       *
031       * - handle_factory: An optional factory  used to create curl handles
032       * - select_timeout: Optional timeout (in seconds) to block before timing
033       *   out while selecting curl handles. Defaults to 1 second.
034       * - options: An associative array of CURLMOPT_* options and
035       *   corresponding values for curl_multi_setopt()
036       *
037       * @param array $options
038       */
039      public function __construct(array $options = [])
040      {
041          $this->factory = isset($options['handle_factory'])
042              ? $options['handle_factory'] : new CurlFactory(50);
043   
044          if (isset($options['select_timeout'])) {
045              $this->selectTimeout = $options['select_timeout'];
046          } elseif ($selectTimeout = getenv('GUZZLE_CURL_SELECT_TIMEOUT')) {
047              $this->selectTimeout = $selectTimeout;
048          } else {
049              $this->selectTimeout = 1;
050          }
051   
052          $this->options = isset($options['options']) ? $options['options'] : [];
053      }
054   
055      public function __get($name)
056      {
057          if ($name === '_mh') {
058              $this->_mh = curl_multi_init();
059   
060              foreach ($this->options as $option => $value) {
061                  // A warning is raised in case of a wrong option.
062                  curl_multi_setopt($this->_mh, $option, $value);
063              }
064   
065              // Further calls to _mh will return the value directly, without entering the
066              // __get() method at all.
067              return $this->_mh;
068          }
069   
070          throw new \BadMethodCallException();
071      }
072   
073      public function __destruct()
074      {
075          if (isset($this->_mh)) {
076              curl_multi_close($this->_mh);
077              unset($this->_mh);
078          }
079      }
080   
081      public function __invoke(RequestInterface $request, array $options)
082      {
083          $easy = $this->factory->create($request, $options);
084          $id = (int) $easy->handle;
085   
086          $promise = new Promise(
087              [$this, 'execute'],
088              function () use ($id) {
089                  return $this->cancel($id);
090              }
091          );
092   
093          $this->addRequest(['easy' => $easy, 'deferred' => $promise]);
094   
095          return $promise;
096      }
097   
098      /**
099       * Ticks the curl event loop.
100       */
101      public function tick()
102      {
103          // Add any delayed handles if needed.
104          if ($this->delays) {
105              $currentTime = Utils::currentTime();
106              foreach ($this->delays as $id => $delay) {
107                  if ($currentTime >= $delay) {
108                      unset($this->delays[$id]);
109                      curl_multi_add_handle(
110                          $this->_mh,
111                          $this->handles[$id]['easy']->handle
112                      );
113                  }
114              }
115          }
116   
117          // Step through the task queue which may add additional requests.
118          P\queue()->run();
119   
120          if ($this->active &&
121              curl_multi_select($this->_mh, $this->selectTimeout) === -1
122          ) {
123              // Perform a usleep if a select returns -1.
124              // See: https://bugs.php.net/bug.php?id=61141
125              usleep(250);
126          }
127   
128          while (curl_multi_exec($this->_mh, $this->active) === CURLM_CALL_MULTI_PERFORM);
129   
130          $this->processMessages();
131      }
132   
133      /**
134       * Runs until all outstanding connections have completed.
135       */
136      public function execute()
137      {
138          $queue = P\queue();
139   
140          while ($this->handles || !$queue->isEmpty()) {
141              // If there are no transfers, then sleep for the next delay
142              if (!$this->active && $this->delays) {
143                  usleep($this->timeToNext());
144              }
145              $this->tick();
146          }
147      }
148   
149      private function addRequest(array $entry)
150      {
151          $easy = $entry['easy'];
152          $id = (int) $easy->handle;
153          $this->handles[$id] = $entry;
154          if (empty($easy->options['delay'])) {
155              curl_multi_add_handle($this->_mh, $easy->handle);
156          } else {
157              $this->delays[$id] = Utils::currentTime() + ($easy->options['delay'] / 1000);
158          }
159      }
160   
161      /**
162       * Cancels a handle from sending and removes references to it.
163       *
164       * @param int $id Handle ID to cancel and remove.
165       *
166       * @return bool True on success, false on failure.
167       */
168      private function cancel($id)
169      {
170          // Cannot cancel if it has been processed.
171          if (!isset($this->handles[$id])) {
172              return false;
173          }
174   
175          $handle = $this->handles[$id]['easy']->handle;
176          unset($this->delays[$id], $this->handles[$id]);
177          curl_multi_remove_handle($this->_mh, $handle);
178          curl_close($handle);
179   
180          return true;
181      }
182   
183      private function processMessages()
184      {
185          while ($done = curl_multi_info_read($this->_mh)) {
186              $id = (int) $done['handle'];
187              curl_multi_remove_handle($this->_mh, $done['handle']);
188   
189              if (!isset($this->handles[$id])) {
190                  // Probably was cancelled.
191                  continue;
192              }
193   
194              $entry = $this->handles[$id];
195              unset($this->handles[$id], $this->delays[$id]);
196              $entry['easy']->errno = $done['result'];
197              $entry['deferred']->resolve(
198                  CurlFactory::finish(
199                      $this,
200                      $entry['easy'],
201                      $this->factory
202                  )
203              );
204          }
205      }
206   
207      private function timeToNext()
208      {
209          $currentTime = Utils::currentTime();
210          $nextTime = PHP_INT_MAX;
211          foreach ($this->delays as $time) {
212              if ($time < $nextTime) {
213                  $nextTime = $time;
214              }
215          }
216   
217          return max(0, $nextTime - $currentTime) * 1000000;
218      }
219  }
220