<?php

Phar::mapPhar('nightwatch-agent.phar');

$_SERVER['SCRIPT_FILENAME'] = 'phar://nightwatch-agent.phar/src/agent.php';
require 'phar://nightwatch-agent.phar/src/agent.php';

__HALT_COMPILER(); ?>
,                    helpers.php  tg  ]         src/Browser.php  tg  Ȟ         src/CheckSignature.php  tg  -         src/Clock.php*  tg*  4         src/Contracts/Browser.php  tg  Ӥ         src/Contracts/Clock.php   tg   ؤ          src/Factories/BrowserFactory.php  tg  2v)         src/Ingest.php  tg  	/         src/IngestDetails.php  tg  >         src/IngestDetailsRepository.php  tg  ih         src/Loop.php	  tg	  zh         src/NullBuffer.php)  tg)  |Vʤ         src/OutputWriter.php  tg  ۤ         src/Payload.phpb  tgb  ߣ         src/Server.php	  tg	  d         src/StreamBuffer.php  tg  qCG1         src/agent.php !  tg !  B         src/bootstrap.php\  tg\  ӗ         vendor/autoload.php  tg  
~         vendor/composer/ClassLoader.php?  tg?  2@u      %   vendor/composer/InstalledVersions.phpD  tgD  (         vendor/composer/LICENSE.  tg.         %   vendor/composer/autoload_classmap.php
I  tg
I  3@֤      "   vendor/composer/autoload_files.php.  tg.  k      '   vendor/composer/autoload_namespaces.php   tg   /t      !   vendor/composer/autoload_psr4.php  tg  6      !   vendor/composer/autoload_real.phpi  tgi  ;l      #   vendor/composer/autoload_static.php5[  tg5[  0٤         vendor/composer/installed.phpU  tgU  t      "   vendor/composer/platform_check.php  tg  "J      "   vendor/evenement/evenement/LICENSE   tg   {I=      /   vendor/evenement/evenement/src/EventEmitter.php  tg  D\$      8   vendor/evenement/evenement/src/EventEmitterInterface.php  tg  ґX      4   vendor/evenement/evenement/src/EventEmitterTrait.phpf  tgf  ޙK;      $   vendor/fig/http-message-util/LICENSE=  tg=  ?      ;   vendor/fig/http-message-util/src/RequestMethodInterface.php  tg  H      8   vendor/fig/http-message-util/src/StatusCodeInterface.php  tg  _-         vendor/psr/http-message/LICENSE=  tg=        0   vendor/psr/http-message/src/MessageInterface.php`  tg`  |      0   vendor/psr/http-message/src/RequestInterface.php  tg  "@      1   vendor/psr/http-message/src/ResponseInterface.phpc
  tgc
  ,       6   vendor/psr/http-message/src/ServerRequestInterface.php'  tg'  1Ͽ      /   vendor/psr/http-message/src/StreamInterface.php  tg        5   vendor/psr/http-message/src/UploadedFileInterface.php~  tg~  :ɬ      ,   vendor/psr/http-message/src/UriInterface.php1  tg1  æ         vendor/react/cache/LICENSEu  tgu  {      %   vendor/react/cache/src/ArrayCache.php  tg  H      )   vendor/react/cache/src/CacheInterface.phpL   tgL   ?1         vendor/react/dns/LICENSEu  tgu  {      +   vendor/react/dns/src/BadServerException.phpt   tgt   $Ѥ      &   vendor/react/dns/src/Config/Config.phpM  tgM  EH      )   vendor/react/dns/src/Config/HostsFile.php  tg  'G      &   vendor/react/dns/src/Model/Message.php  tg  :ݤ      %   vendor/react/dns/src/Model/Record.php  tg  +Ф      .   vendor/react/dns/src/Protocol/BinaryDumper.php|  tg|  `*X      (   vendor/react/dns/src/Protocol/Parser.php,  tg,  }x      .   vendor/react/dns/src/Query/CachingExecutor.php
  tg
  ýȤ      4   vendor/react/dns/src/Query/CancellationException.php   tg   r      +   vendor/react/dns/src/Query/CoopExecutor.php  tg  ,      0   vendor/react/dns/src/Query/ExecutorInterface.php  tg  J      /   vendor/react/dns/src/Query/FallbackExecutor.php  tg  (hX      0   vendor/react/dns/src/Query/HostsFileExecutor.php5  tg5  ۩8      $   vendor/react/dns/src/Query/Query.php,  tg,  d=ʤ      ,   vendor/react/dns/src/Query/RetryExecutor.php
  tg
  N      9   vendor/react/dns/src/Query/SelectiveTransportExecutor.php)  tg)  ]S      3   vendor/react/dns/src/Query/TcpTransportExecutor.php	7  tg	7  Q      /   vendor/react/dns/src/Query/TimeoutException.phpx   tgx   ͤ      .   vendor/react/dns/src/Query/TimeoutExecutor.php,  tg,  4ٴ      3   vendor/react/dns/src/Query/UdpTransportExecutor.php!  tg!        0   vendor/react/dns/src/RecordNotFoundException.phpy   tgy   Ĥ      )   vendor/react/dns/src/Resolver/Factory.php!  tg!  y      *   vendor/react/dns/src/Resolver/Resolver.phpP  tgP  ^O      3   vendor/react/dns/src/Resolver/ResolverInterface.php  tg  ,<*         vendor/react/event-loop/LICENSEu  tgu  {      )   vendor/react/event-loop/src/ExtEvLoop.php  tg  Ix      ,   vendor/react/event-loop/src/ExtEventLoop.php   tg   +&Ť      ,   vendor/react/event-loop/src/ExtLibevLoop.phpp  tgp  %{      /   vendor/react/event-loop/src/ExtLibeventLoop.php"  tg"  Q[      )   vendor/react/event-loop/src/ExtUvLoop.php6%  tg6%  
챮      '   vendor/react/event-loop/src/Factory.phpV  tgV  |      $   vendor/react/event-loop/src/Loop.phpG  tgG  S6      -   vendor/react/event-loop/src/LoopInterface.phpK  tgK  Io      .   vendor/react/event-loop/src/SignalsHandler.php9  tg9  Ǿ =      0   vendor/react/event-loop/src/StreamSelectLoop.phpQ/  tgQ/  ڤ      4   vendor/react/event-loop/src/Tick/FutureTickQueue.php  tg  c      +   vendor/react/event-loop/src/Timer/Timer.phpR  tgR  ~      ,   vendor/react/event-loop/src/Timer/Timers.php  tg  }x      .   vendor/react/event-loop/src/TimerInterface.php  tg  b@         vendor/react/http/LICENSEu  tgu  {      !   vendor/react/http/src/Browser.phpF}  tgF}  .#1      '   vendor/react/http/src/Client/Client.php  tg  T      $   vendor/react/http/src/HttpServer.php6=  tg6=  7      ,   vendor/react/http/src/Io/AbstractMessage.php  tg  |d      ,   vendor/react/http/src/Io/AbstractRequest.php+  tg+  pX=      )   vendor/react/http/src/Io/BufferedBody.php  tg  ;ݩ      +   vendor/react/http/src/Io/ChunkedDecoder.phpu  tgu  P/f      +   vendor/react/http/src/Io/ChunkedEncoder.php  tg  $7      4   vendor/react/http/src/Io/ClientConnectionManager.phpd  tgd  @ˤ      /   vendor/react/http/src/Io/ClientRequestState.php;  tg;  wʤ      0   vendor/react/http/src/Io/ClientRequestStream.phpC)  tgC)  73      "   vendor/react/http/src/Io/Clock.php  tg  T敤      2   vendor/react/http/src/Io/CloseProtectionStream.php|  tg|  mP      ,   vendor/react/http/src/Io/EmptyBodyStream.php  tg  ͎      +   vendor/react/http/src/Io/HttpBodyStream.php  tg  A u      $   vendor/react/http/src/Io/IniUtil.php  tg  
`      0   vendor/react/http/src/Io/LengthLimitedStream.phpe  tge  ;Tڤ      -   vendor/react/http/src/Io/MiddlewareRunner.php  tg  g      ,   vendor/react/http/src/Io/MultipartParser.phpB$  tgB$  ^;+      .   vendor/react/http/src/Io/PauseBufferStream.php^  tg^        /   vendor/react/http/src/Io/ReadableBodyStream.phpl  tgl  #`Ф      0   vendor/react/http/src/Io/RequestHeaderParser.phpT  tgT  H      #   vendor/react/http/src/Io/Sender.phpj  tgj  
      ,   vendor/react/http/src/Io/StreamingServer.phpI  tgI  6e      (   vendor/react/http/src/Io/Transaction.php-  tg-  ͤ      )   vendor/react/http/src/Io/UploadedFile.php#
  tg#
  Z@      )   vendor/react/http/src/Message/Request.php	  tg	  8%-      *   vendor/react/http/src/Message/Response.php9  tg9  f~      3   vendor/react/http/src/Message/ResponseException.php  tg  w      /   vendor/react/http/src/Message/ServerRequest.php.  tg.  ,ʤ      %   vendor/react/http/src/Message/Uri.phpZ%  tgZ%        F   vendor/react/http/src/Middleware/LimitConcurrentRequestsMiddleware.php`  tg`  ԙ      @   vendor/react/http/src/Middleware/RequestBodyBufferMiddleware.php  tg  X.      @   vendor/react/http/src/Middleware/RequestBodyParserMiddleware.php  tg  }5%      ?   vendor/react/http/src/Middleware/StreamingRequestMiddleware.phpK
  tgK
  ꐤ          vendor/react/http/src/Server.phpQ  tgQ  $	.         vendor/react/promise/LICENSEg  tgg  F      %   vendor/react/promise/src/Deferred.php/  tg/  aΗ      9   vendor/react/promise/src/Exception/CompositeException.php  tg  G      6   vendor/react/promise/src/Exception/LengthException.php   tg   .      7   vendor/react/promise/src/Internal/CancellationQueue.php1  tg1  L;      6   vendor/react/promise/src/Internal/FulfilledPromise.php	  tg	  f      5   vendor/react/promise/src/Internal/RejectedPromise.php  tg  0C      $   vendor/react/promise/src/Promise.phpU(  tgU(        -   vendor/react/promise/src/PromiseInterface.phpu  tgu  L&      &   vendor/react/promise/src/functions.php,  tg,  [      .   vendor/react/promise/src/functions_include.php   tg   "         vendor/react/socket/LICENSEu  tgu  {      &   vendor/react/socket/src/Connection.php/  tg/  u      /   vendor/react/socket/src/ConnectionInterface.php  tg  8      %   vendor/react/socket/src/Connector.php0  tg0  iJB;      .   vendor/react/socket/src/ConnectorInterface.phpK  tgK  פ      (   vendor/react/socket/src/DnsConnector.php=  tg=  j      $   vendor/react/socket/src/FdServer.php7  tg7  _      -   vendor/react/socket/src/FixedUriConnector.phpJ  tgJ  ,;      :   vendor/react/socket/src/HappyEyeBallsConnectionBuilder.php-  tg-  P-      2   vendor/react/socket/src/HappyEyeBallsConnector.php  tg  Ť      *   vendor/react/socket/src/LimitingServer.php  tg  ]2$      +   vendor/react/socket/src/SecureConnector.php  tg  +~A      (   vendor/react/socket/src/SecureServer.php  tg  :1$+      "   vendor/react/socket/src/Server.php  tg  3      +   vendor/react/socket/src/ServerInterface.php  tg  RF      (   vendor/react/socket/src/SocketServer.php"  tg"  >      ,   vendor/react/socket/src/StreamEncryption.php  tg  J&>      (   vendor/react/socket/src/TcpConnector.php;  tg;  PТ      %   vendor/react/socket/src/TcpServer.php"  tg"  5      ,   vendor/react/socket/src/TimeoutConnector.php  tg  Z-5j      )   vendor/react/socket/src/UnixConnector.php  tg  ,Ϥ      &   vendor/react/socket/src/UnixServer.php  tg  Fnޤ         vendor/react/stream/LICENSEu  tgu  {      +   vendor/react/stream/src/CompositeStream.php  tg  rt      0   vendor/react/stream/src/DuplexResourceStream.php  tg  F      1   vendor/react/stream/src/DuplexStreamInterface.php  tg  q      2   vendor/react/stream/src/ReadableResourceStream.php  tg  p]      3   vendor/react/stream/src/ReadableStreamInterface.php7  tg7  rg      )   vendor/react/stream/src/ThroughStream.php  tg  eä          vendor/react/stream/src/Util.php	  tg	  A      2   vendor/react/stream/src/WritableResourceStream.php3  tg3  ߶      3   vendor/react/stream/src/WritableStreamInterface.php9  tg9  }K      <?php

namespace NightwatchAgent_kden27khxA4QoEfj\Nightwatch;

use RuntimeException;
use Throwable;
use function array_keys;
use function array_reduce;
use function fclose;
use function feof;
use function fread;
use function fwrite;
use function gettype;
use function intval;
use function is_callable;
use function stream_get_meta_data;
use function stream_set_timeout;
use function strlen;
use function substr;
/**
 * @param  resource  $stream
 * @param  (callable(): string)|string  $payload
 */
function fwrite_all($stream, callable|string $payload): void
{
    $payload = is_callable($payload) ? $payload() : $payload;
    $originalPayloadLength = strlen($payload);
    $written = 0;
    while (\true) {
        $thisWrite = fwrite($stream, $payload);
        if ($thisWrite === \false) {
            throw runtime_exception_with_steam_meta('Unable to write to stream', $stream);
        }
        $written += $thisWrite;
        if ($written >= $originalPayloadLength) {
            return;
        }
        $payload = substr($payload, $thisWrite);
    }
}
/**
 * @param  resource  $stream
 * @param  int<1, max>  $length
 */
function fread_all($stream, int $length): string
{
    $content = '';
    $attempts = 0;
    do {
        $thisRead = fread($stream, $length);
        if ($thisRead === \false) {
            throw runtime_exception_with_steam_meta('Unable to read from stream', $stream);
        }
        $content .= $thisRead;
        $attempts++;
    } while (strlen($content) < $length && !feof($stream) && $attempts < 5);
    return $content;
}
/**
 * @param  resource  $stream
 */
function stream_get_formatted_meta_data($stream): string
{
    if (stream_closed($stream)) {
        return 'closed: true';
    }
    $meta = stream_get_meta_data($stream);
    return array_reduce(array_keys($meta), static function ($carry, $key) use ($meta) {
        try {
            return $carry . $key . ': ' . match ($meta[$key]) {
                \true => 'true',
                \false => 'false',
                default => $meta[$key],
            } . \PHP_EOL;
        } catch (Throwable) {
            // @phpstan-ignore catch.neverThrown
            return $carry;
        }
    }, '');
}
/**
 * @param  resource  $stream
 */
function fclose_safely($stream): void
{
    try {
        if (!stream_closed($stream)) {
            fclose($stream);
        }
    } catch (Throwable) {
        //
    }
}
/**
 * @param  resource  $stream
 */
function stream_closed($stream): bool
{
    return gettype($stream) === 'resource (closed)';
}
/**
 * @param  resource  $stream
 */
function runtime_exception_with_steam_meta(string $message, $stream): RuntimeException
{
    return new RuntimeException($message . \PHP_EOL . '---' . \PHP_EOL . stream_get_formatted_meta_data($stream));
}
/**
 * @param  resource  $stream
 */
function stream_configure_read_timeout($stream, float $timeout): void
{
    $timeout = ['seconds' => $seconds = (int) $timeout, 'microseconds' => intval(($timeout - $seconds) * 1000000)];
    $timeoutConfigured = stream_set_timeout($stream, $timeout['seconds'], $timeout['microseconds']);
    if ($timeoutConfigured === \false) {
        throw runtime_exception_with_steam_meta('Failed configuring agent read timeout', $stream);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent;

use NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent\Contracts\Browser as BrowserContract;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Browser as ReactBrowser;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\PromiseInterface;
class Browser implements BrowserContract
{
    public function __construct(private ReactBrowser $browser)
    {
        //
    }
    /**
     * @param  array<string, string>  $headers
     */
    public function post(string $url, array $headers = [], string $body = ''): PromiseInterface
    {
        return $this->browser->post($url, [...$headers], $body);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent;

use Closure;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\TimerInterface;
use function clearstatcache;
use function file_get_contents;
class CheckSignature
{
    private TimerInterface $checkTimer;
    private TimerInterface $shutdownTimer;
    /**
     * @param  (Closure(string $signature): void)  $onCheckSignature
     * @param  (Closure(int $shuttingDownIn): void)  $onShutdownInitiated
     * @param  (Closure(): void)  $onShutdown
     */
    public function __construct(private LoopInterface $loop, private string $signaturePath, private string $expectedSignature, private int $shutdownDelayInMinutes, private Closure $onCheckSignature, private Closure $onShutdownInitiated, private Closure $onShutdown)
    {
        //
    }
    public function start(): void
    {
        $this->checkTimer = $this->loop->addPeriodicTimer(60, $this->check(...));
    }
    private function check(): void
    {
        clearstatcache(clear_realpath_cache: \true, filename: $this->signaturePath);
        $signature = @file_get_contents($this->signaturePath) ?: '';
        ($this->onCheckSignature)($signature);
        if ($signature === $this->expectedSignature || $signature === '') {
            return;
        }
        $this->scheduledShutdown();
    }
    private function scheduledShutdown(): void
    {
        $this->loop->cancelTimer($this->checkTimer);
        $shuttingDownIn = $this->shutdownDelayInMinutes;
        ($this->onShutdownInitiated)($shuttingDownIn);
        $this->shutdownTimer = $this->loop->addPeriodicTimer(60, function () use (&$shuttingDownIn) {
            $shuttingDownIn--;
            if ($shuttingDownIn <= 0) {
                $this->loop->cancelTimer($this->shutdownTimer);
                ($this->onShutdown)();
            } else {
                ($this->onShutdownInitiated)($shuttingDownIn);
            }
        });
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent;

use NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent\Contracts\Clock as ClockContract;
use function time;
class Clock implements ClockContract
{
    public function time(): int
    {
        return time();
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent\Contracts;

use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\ResponseInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\PromiseInterface;
interface Browser
{
    /**
     * @param  array<string, string>  $headers
     * @return PromiseInterface<ResponseInterface>
     */
    public function post(string $url, array $headers = [], string $body = ''): PromiseInterface;
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent\Contracts;

interface Clock
{
    public function time(): int;
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent\Factories;

use NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent\Browser as NightwatchBrowser;
use NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent\Contracts\Browser as BrowserContract;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Browser as ReactBrowser;
use NightwatchAgent_kden27khxA4QoEfj\React\Socket\Connector;
class BrowserFactory
{
    /**
     * @param  array<string, string>  $headers
     */
    public function __invoke(float $connectionTimeout, float $timeout, array $headers = [], ?string $baseUrl = null): BrowserContract
    {
        $connector = new Connector(['timeout' => $connectionTimeout]);
        $browser = (new ReactBrowser($connector))->withTimeout($timeout)->withBase($baseUrl)->withoutHeader('User-Agent');
        foreach ($headers as $key => $value) {
            $browser = $browser->withHeader($key, $value);
        }
        return new NightwatchBrowser($browser);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent;

use Closure;
use NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent\Contracts\Browser;
use NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent\Contracts\Clock;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\ResponseInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\TimerInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Message\ResponseException;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\PromiseInterface;
use RuntimeException;
use Throwable;
use function array_key_last;
use function call_user_func;
use function count;
use function gzencode;
use function json_decode;
use function microtime;
use function NightwatchAgent_kden27khxA4QoEfj\React\Promise\all;
use function strlen;
use function substr;
class Ingest
{
    /**
     * @var array<int<0, max>, PromiseInterface<null>>
     */
    private array $concurrentRequests = [];
    private ?TimerInterface $digestDelayTimer = null;
    private StreamBuffer|NullBuffer $buffer;
    private StreamBuffer $streamBufferBackup;
    /**
     * @param  (Closure(ResponseInterface $response, float $duration): mixed)  $onIngestSuccess
     * @param  (Closure(string $message, float $duration): mixed)  $onIngestError
     * @param  (Closure(string $message, float $duration): mixed)  $onOverQuota
     */
    public function __construct(private LoopInterface $loop, private Browser $browser, private IngestDetailsRepository $ingestDetails, private Clock $clock, StreamBuffer $buffer, private int $concurrentRequestLimit, private int $maxBufferDurationInSeconds, private Closure $onIngestSuccess, private Closure $onIngestError, private Closure $onOverQuota)
    {
        $this->buffer = $this->streamBufferBackup = $buffer;
    }
    public function write(string $payload): void
    {
        if ($this->buffer->isNotEmpty() && $this->buffer->willExceedThresholdWith($payload)) {
            $this->cancelDigestDelay();
            $this->digest();
        }
        $this->buffer->write($payload);
        if ($this->buffer->reachedThreshold()) {
            $this->cancelDigestDelay();
            $this->digest();
        } elseif ($this->buffer->isNotEmpty()) {
            $this->digestDelayTimer ??= $this->loop->addTimer($this->maxBufferDurationInSeconds, function () {
                $this->digestDelayTimer = null;
                $this->digest();
            });
        }
    }
    /**
     * @return PromiseInterface<null>
     */
    public function forceDigest(): PromiseInterface
    {
        $this->cancelDigestDelay();
        if ($this->buffer->isNotEmpty()) {
            $this->digest();
        }
        return all($this->concurrentRequests)->then(static fn() => null);
    }
    public function pauseIngestion(): void
    {
        $this->buffer = new NullBuffer();
        $this->streamBufferBackup->flush();
    }
    public function resumeIngestion(): void
    {
        $this->buffer = $this->streamBufferBackup;
    }
    private function digest(): void
    {
        $payload = $this->buffer->pull();
        if (count($this->concurrentRequests) >= $this->concurrentRequestLimit) {
            call_user_func($this->onIngestError, "Exceeded concurrent request limit. [{$this->concurrentRequestLimit}] requests are processing", 0.0);
            return;
        }
        // TODO determine what level is optimal here
        $payload = gzencode($payload);
        if ($payload === \false) {
            call_user_func($this->onIngestError, 'Unable to compress payload.', 0.0);
            return;
        }
        $start = microtime(\true);
        $currentRequestKey = (array_key_last($this->concurrentRequests) ?? -1) + 1;
        ($this->concurrentRequests[$currentRequestKey] = $this->ingestDetails->get()->then(function (?IngestDetails $ingestDetails) use ($payload, &$start): PromiseInterface {
            $start = microtime(\true);
            if ($ingestDetails === null) {
                throw new RuntimeException('No authentication details');
            }
            if ($this->clock->time() > $ingestDetails->expiresAt) {
                throw new RuntimeException('Authentication token expired');
            }
            return $this->browser->post(url: $ingestDetails->ingestUrl, headers: ['authorization' => "Bearer {$ingestDetails->token}"], body: $payload);
        })->then(function (ResponseInterface $response) use (&$start): null {
            $duration = microtime(\true) - $start;
            [$message, $stop, $refreshIn] = $this->parseResponse($response);
            if ($stop) {
                $this->stop($this->onOverQuota, $duration, $message, $refreshIn);
            } else {
                call_user_func($this->onIngestSuccess, $response, microtime(\true) - $start);
            }
            return null;
        })->catch(function (Throwable $e) use (&$start): null {
            $duration = microtime(\true) - $start;
            [$message, $stop, $refreshIn] = $this->parseException($e);
            if ($stop) {
                $this->stop($this->onIngestError, $duration, $message, $refreshIn);
            } else {
                call_user_func($this->onIngestError, $message, $duration);
            }
            return null;
        }))->finally(function () use ($currentRequestKey): void {
            unset($this->concurrentRequests[$currentRequestKey]);
        });
    }
    private function stop(callable $errorHandler, float $duration, string $message, float|int|null $refreshIn = null): void
    {
        $this->pauseIngestion();
        $this->ingestDetails->markOverQuota($refreshIn);
        call_user_func($errorHandler, $message, $duration);
    }
    /**
     * @return array{0: string, 1: bool, 2: null|int|float}
     */
    private function parseException(Throwable $e): array
    {
        return $e instanceof ResponseException ? $this->parseResponse($e->getResponse()) : [$e->getMessage(), \false, null];
    }
    /**
     * @return array{0: string, 1: bool, 2: null|int|float}
     */
    private function parseResponse(ResponseInterface $response): array
    {
        $message = (string) $response->getBody();
        $stop = \false;
        $refreshIn = null;
        try {
            /** @var array{ message?: string, refresh_in?: int|float, stop?: bool } $json */
            $json = json_decode($message, associative: \true, flags: \JSON_THROW_ON_ERROR);
            $message = $json['message'] ?? $message;
            $stop = $json['stop'] ?? $stop;
            $refreshIn = $json['refresh_in'] ?? $refreshIn;
        } catch (Throwable $exception) {
            //
        }
        if (strlen($message) > 1005) {
            $message = substr($message, 0, 1000) . '[...]';
        }
        return ["{$response->getStatusCode()} [{$message}]", $stop, $refreshIn];
    }
    private function cancelDigestDelay(): void
    {
        if ($this->digestDelayTimer !== null) {
            $this->loop->cancelTimer($this->digestDelayTimer);
            $this->digestDelayTimer = null;
        }
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent;

class IngestDetails
{
    public function __construct(public string $token, public int $expiresIn, public string $ingestUrl, public int $refreshIn, public int $expiresAt)
    {
        //
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent;

use Closure;
use NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent\Contracts\Browser;
use NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent\Contracts\Clock;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\ResponseInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\TimerInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Message\ResponseException;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\PromiseInterface;
use RuntimeException;
use Throwable;
use function array_fill;
use function call_user_func;
use function is_array;
use function is_int;
use function is_string;
use function json_decode;
use function microtime;
use function NightwatchAgent_kden27khxA4QoEfj\React\Promise\resolve;
use function strlen;
use function substr;
class IngestDetailsRepository
{
    private bool $overQuota = \false;
    /**
     * @var PromiseInterface<IngestDetails|null>|null
     */
    private ?PromiseInterface $ingestDetails = null;
    private bool $hasAuthenticated = \false;
    private int $consecutiveFailures = 0;
    private ?TimerInterface $refreshTimer = null;
    /**
     * @var list<int|float>|null
     */
    private ?array $quickRetryStrategyDurationsCache = null;
    /**
     * @param  (Closure(IngestDetails $ingestDetails, float $duration): mixed)  $onAuthenticationSuccess
     * @param  (Closure(string $message, float $duration): mixed)  $onAuthenticationError
     * @param  (Closure(): mixed)  $onUnderQuota
     */
    public function __construct(private LoopInterface $loop, private Browser $browser, private Clock $clock, private Closure $onAuthenticationSuccess, private Closure $onAuthenticationError, private Closure $onUnderQuota)
    {
        //
    }
    public function hydrate(): void
    {
        $this->get();
    }
    /**
     * @return PromiseInterface<IngestDetails|null>
     */
    public function get(): PromiseInterface
    {
        return $this->ingestDetails ??= $this->refresh();
    }
    public function markOverQuota(int|float|null $refreshIn = null): void
    {
        $this->overQuota = \true;
        $this->loop->cancelTimer($this->refreshTimer);
        // @phpstan-ignore argument.type
        $this->scheduleRefreshIn($refreshIn ?? 60 * 15);
    }
    /**
     * @return PromiseInterface<IngestDetails|null>
     */
    private function refresh(): PromiseInterface
    {
        $start = microtime(\true);
        $duration = null;
        return $this->browser->post('/api/agent-auth', body: '{}')->then(function (ResponseInterface $response) use ($start, &$duration): IngestDetails {
            $duration = microtime(\true) - $start;
            $ingestDetails = $this->parseResponse($response);
            $this->scheduleRefreshIn($ingestDetails->refreshIn);
            call_user_func($this->onAuthenticationSuccess, $ingestDetails, $duration);
            if ($this->overQuota) {
                $this->overQuota = \false;
                call_user_func($this->onUnderQuota);
            }
            $this->hasAuthenticated = \true;
            $this->consecutiveFailures = 0;
            return $ingestDetails;
        })->catch(function (Throwable $e) use ($start, &$duration): null {
            $this->consecutiveFailures++;
            $duration ??= microtime(\true) - $start;
            [$message, $stop, $refreshIn] = $this->parseException($e);
            if ($stop) {
                $this->ingestDetails = resolve(null);
            }
            $this->scheduleRefreshIn($refreshIn);
            call_user_func($this->onAuthenticationError, $message, $duration);
            return null;
        });
    }
    private function scheduleRefreshIn(int|float $seconds): void
    {
        $this->refreshTimer = $this->loop->addTimer($seconds, function (): void {
            $this->refresh()->then(function (?IngestDetails $ingestDetails): void {
                if ($ingestDetails) {
                    $this->ingestDetails = resolve($ingestDetails);
                }
            });
        });
    }
    private function parseResponse(ResponseInterface $response): IngestDetails
    {
        $body = $response->getBody()->getContents();
        $data = json_decode($body, associative: \true, flags: \JSON_THROW_ON_ERROR);
        if (!is_array($data) || !is_string($data['token'] ?? null) || !is_int($data['expires_in'] ?? null) || !is_int($data['refresh_in'] ?? null) || !is_string($data['ingest_url'] ?? null)) {
            throw new RuntimeException("Invalid authentication response [{$body}]");
        }
        return new IngestDetails(token: $data['token'], expiresIn: $data['expires_in'], ingestUrl: $data['ingest_url'], refreshIn: $data['refresh_in'], expiresAt: $data['expires_in'] + $this->clock->time());
    }
    /**
     * @return array{0: string, 1: bool, 2: int|float}
     */
    private function parseException(Throwable $e): array
    {
        return $e instanceof ResponseException ? $this->parseResponseException($e) : $this->parseNonResponseException($e);
    }
    /**
     * @return array{0: string, 1: bool, 2: int|float}
     */
    private function parseResponseException(ResponseException $e): array
    {
        $message = (string) $e->getResponse()->getBody();
        $stop = \false;
        $refreshIn = null;
        try {
            /** @var array{ message?: string, refresh_in?: int|float, stop?: bool } $json */
            $json = json_decode($message, associative: \true, flags: \JSON_THROW_ON_ERROR);
            $message = $json['message'] ?? $message;
            $stop = $json['stop'] ?? $stop;
            $refreshIn = $json['refresh_in'] ?? $refreshIn;
        } catch (Throwable $exception) {
            //
        }
        if (strlen($message) > 1005) {
            $message = substr($message, 0, 1000) . '[...]';
        }
        $refreshIn ??= $this->hasAuthenticated ? $this->slowRetryStrategy() : $this->quickRetryStrategy();
        return ["{$e->getResponse()->getStatusCode()} [{$message}]", $stop, $refreshIn];
    }
    /**
     * @return array{0: string, 1: bool, 2: int|float}
     */
    private function parseNonResponseException(Throwable $e): array
    {
        return $this->hasAuthenticated ? [$e->getMessage(), \false, $this->slowRetryStrategy()] : [$e->getMessage(), \false, $this->quickRetryStrategy()];
    }
    private function quickRetryStrategy(): int|float
    {
        $strategy = $this->quickRetryStrategyDurationsCache ??= [2.5, 5, 10, 15, 30, 60, 120, 240, ...array_fill(0, 12, 300)];
        return $strategy[$this->consecutiveFailures - 1] ?? 3600;
    }
    private function slowRetryStrategy(): int
    {
        return $this->consecutiveFailures < 13 ? 300 : 3600;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent;

use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\TimerInterface;
class Loop implements LoopInterface
{
    private bool $running = \false;
    public function __construct(private LoopInterface $loop)
    {
        //
    }
    public function running(): bool
    {
        return $this->running;
    }
    public function run(): void
    {
        $this->running = \true;
        $this->loop->run();
    }
    public function stop(): void
    {
        $this->running = \false;
        $this->loop->stop();
    }
    /**
     * @param  resource  $stream
     * @param  callable  $listener
     */
    public function addReadStream($stream, $listener): void
    {
        $this->loop->addReadStream($stream, $listener);
    }
    /**
     * @param  resource  $stream
     * @param  callable  $listener
     */
    public function addWriteStream($stream, $listener): void
    {
        $this->loop->addWriteStream($stream, $listener);
    }
    /*
     * @param resource $stream
     */
    public function removeReadStream($stream): void
    {
        $this->loop->removeReadStream($stream);
    }
    /**
     * @param  resource  $stream
     */
    public function removeWriteStream($stream): void
    {
        $this->loop->removeWriteStream($stream);
    }
    /**
     * @param  int|float  $interval
     * @param  callable  $callback
     */
    public function addTimer($interval, $callback): TimerInterface
    {
        return $this->loop->addTimer($interval, $callback);
    }
    /**
     * @param  int|float  $interval
     * @param  callable  $callback
     */
    public function addPeriodicTimer($interval, $callback): TimerInterface
    {
        return $this->loop->addPeriodicTimer($interval, $callback);
    }
    public function cancelTimer(TimerInterface $timer): void
    {
        $this->loop->cancelTimer($timer);
    }
    /**
     * @param  callable  $listener
     */
    public function futureTick($listener): void
    {
        $this->loop->futureTick($listener);
    }
    /**
     * @param  int  $signal
     * @param  callable  $listener
     */
    public function addSignal($signal, $listener): void
    {
        $this->loop->addSignal($signal, $listener);
    }
    /**
     * @param  int  $signal
     * @param  callable  $listener
     */
    public function removeSignal($signal, $listener): void
    {
        $this->loop->removeSignal($signal, $listener);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent;

class NullBuffer
{
    public function write(string $payload): void
    {
        //
    }
    public function reachedThreshold(): bool
    {
        return \false;
    }
    public function willExceedThresholdWith(string $payload): bool
    {
        return \false;
    }
    /**
     * @return non-empty-string
     */
    public function pull(): string
    {
        return '{"records":[]}';
    }
    public function isNotEmpty(): bool
    {
        return \false;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent;

use NightwatchAgent_kden27khxA4QoEfj\React\Stream\WritableResourceStream;
use function fflush;
use function NightwatchAgent_kden27khxA4QoEfj\Nightwatch\fwrite_all;
class OutputWriter
{
    /**
     * @param  resource  $syncStream
     */
    public function __construct(private Loop $loop, private $syncStream, private ?WritableResourceStream $asyncStream)
    {
        //
    }
    public function write(string $message): void
    {
        if ($this->loop->running() && $this->asyncStream !== null) {
            $this->asyncStream->write($message);
        } else {
            fwrite_all($this->syncStream, $message);
            fflush($this->syncStream);
        }
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent;

use function count;
use function explode;
use function strlen;
class Payload
{
    public const EXPECTED_PAYLOAD_VERSION = 'v1';
    public string $value = '';
    public string $version = '';
    public string $tokenHash = '';
    public ?int $length = null;
    public bool $complete = \false;
    public function append(string $chunk): void
    {
        $this->value .= $chunk;
        $this->parsePayload();
        $this->complete = $this->length === strlen($this->version) + 1 + strlen($this->tokenHash) + 1 + strlen($this->value);
    }
    private function parsePayload(): void
    {
        if ($this->length !== null) {
            return;
        }
        $bits = explode(':', $this->value, 4);
        if (count($bits) !== 4) {
            return;
        }
        $this->length = (int) $bits[0];
        $this->version = $bits[1];
        $this->tokenHash = $bits[2];
        $this->value = $bits[3];
    }
    public function versionIsValid(): bool
    {
        return $this->version === self::EXPECTED_PAYLOAD_VERSION;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent;

use Closure;
use NightwatchAgent_kden27khxA4QoEfj\React\Socket\ConnectionInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Socket\ServerInterface;
use Throwable;
use function call_user_func;
class Server
{
    /**
     * @param  (Closure(): ServerInterface)  $serverResolver
     * @param  (Closure(): mixed)  $onServerStarted
     * @param  (Closure(string $message): mixed)  $onServerError
     * @param  (Closure(string $message): mixed)  $onConnectionError
     * @param  (Closure(string $payload): mixed)  $onPayloadReceived
     * @param  (Closure(): mixed)  $onInvalidPayloadVersion
     * @param  (Closure(): mixed)  $onInvalidTokenHash
     */
    public function __construct(private Closure $serverResolver, private string $tokenHash, private Closure $onServerStarted, private Closure $onServerError, private Closure $onConnectionError, private Closure $onPayloadReceived, private Closure $onInvalidPayloadVersion, private Closure $onInvalidTokenHash)
    {
        //
    }
    public function start(): void
    {
        $server = call_user_func($this->serverResolver);
        $server->on('connection', function (ConnectionInterface $connection) use ($server): void {
            $payload = new Payload();
            $connection->on('data', static function (string $chunk) use ($connection, $payload): void {
                $payload->append($chunk);
                if (!$payload->complete) {
                    return;
                }
                $connection->end('2:OK');
            });
            $connection->on('close', function () use ($server, $payload) {
                if (!$payload->complete) {
                    call_user_func($this->onConnectionError, "Incomplete payload received. Length: [{$payload->length}] Value: [{$payload->value}]");
                    return;
                }
                if (!$payload->versionIsValid()) {
                    $server->close();
                    call_user_func($this->onInvalidPayloadVersion);
                    return;
                }
                if ($payload->tokenHash !== $this->tokenHash) {
                    call_user_func($this->onInvalidTokenHash);
                    return;
                }
                if ($payload->value === 'PING') {
                    return;
                }
                call_user_func($this->onPayloadReceived, $payload->value);
            });
            $connection->on('error', function (Throwable $e): void {
                call_user_func($this->onConnectionError, $e->getMessage());
            });
        });
        $server->on('error', function (Throwable $e): void {
            call_user_func($this->onServerError, $e);
        });
        call_user_func($this->onServerStarted);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent;

use function strlen;
use function substr;
class StreamBuffer
{
    private string $buffer = '';
    public function __construct(private int $threshold)
    {
        //
    }
    public function write(string $payload): void
    {
        $input = substr($payload, 1, -1);
        if ($this->buffer === '') {
            $this->buffer = $input;
        } else {
            $this->buffer .= ",{$input}";
        }
    }
    public function reachedThreshold(): bool
    {
        return strlen($this->buffer) >= $this->threshold;
    }
    public function willExceedThresholdWith(string $payload): bool
    {
        // -2 to account for the removal of the `[` and `]` characters when
        // appending to the stream.
        return strlen($this->buffer) + (strlen($payload) - 2) > $this->threshold;
    }
    /**
     * @return non-empty-string
     */
    public function pull(): string
    {
        $payload = '{"records":[' . $this->buffer . ']}';
        $this->buffer = '';
        return $payload;
    }
    public function isNotEmpty(): bool
    {
        return $this->buffer !== '';
    }
    public function flush(): void
    {
        $this->buffer = '';
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent;

use Closure;
use NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent\Contracts\Browser;
use NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent\Contracts\Clock as ClockContract;
use NightwatchAgent_kden27khxA4QoEfj\Laravel\NightwatchAgent\Factories\BrowserFactory;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\ResponseInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Loop as BaseLoop;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\StreamSelectLoop;
use NightwatchAgent_kden27khxA4QoEfj\React\Socket\ServerInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Socket\TcpServer;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\WritableResourceStream;
use function date;
use function file_get_contents;
use function gethostname;
use function hash;
use function is_file;
use function preg_replace;
use function realpath;
use function round;
use function rtrim;
use function str_replace;
use function strtolower;
use function substr;
require __DIR__ . '/bootstrap.php';
/*
 * Testing...
 */
/** @var (Closure(float $connectionTimeout, float $timeout, array<string, string> $headers, ?string $baseUrl): Browser)|null $browserFactory */
$browserFactory ??= null;
/** @var (Closure(): ServerInterface)|null $serverResolver */
$serverResolver ??= null;
/** @var ?LoopInterface $loop */
$loop ??= null;
/** @var ?ClockContract $clock */
$clock ??= null;
/** @var ?int $maxBufferLength */
$maxBufferLength ??= null;
/*
 * Input...
 */
/** @var ?string $refreshToken */
$refreshToken ??= $_SERVER['NIGHTWATCH_TOKEN'] ?? '';
/** @var string $refreshToken */
/** @var ?string $baseUrl */
$baseUrl ??= $_SERVER['NIGHTWATCH_BASE_URL'] ?? 'https://nightwatch.laravel.com';
/** @var string $baseUrl */
/** @var ?string $listenOn */
$listenOn ??= $_SERVER['NIGHTWATCH_INGEST_URI'] ?? '127.0.0.1:2407';
/** @var string $listenOn */
/** @var ?float $authenticationConnectionTimeout */
$authenticationConnectionTimeout ??= 5;
// @phpstan-ignore varTag.nativeType
/** @var ?float $authenticationTimeout */
$authenticationTimeout ??= 10;
// @phpstan-ignore varTag.nativeType
/** @var ?float $ingestConnectionTimeout */
$ingestConnectionTimeout ??= 5;
// @phpstan-ignore varTag.nativeType
/** @var ?float $ingestTimeout */
$ingestTimeout ??= 10;
// @phpstan-ignore varTag.nativeType
/** @var ?string $server */
$server ??= (string) gethostname();
// @phpstan-ignore varTag.nativeType
/** @var ?bool $silent */
$silent ??= strtolower($_SERVER['NIGHTWATCH_AGENT_LOG_LEVEL'] ?? '') === 'critical';
// @phpstan-ignore argument.type, varTag.nativeType
/** @var ?bool $quiet */
$quiet ??= strtolower($_SERVER['NIGHTWATCH_AGENT_LOG_LEVEL'] ?? '') === 'error';
// @phpstan-ignore argument.type, varTag.nativeType
/** @var ?bool $verbose */
$verbose ??= strtolower($_SERVER['NIGHTWATCH_AGENT_LOG_LEVEL'] ?? '') === 'verbose';
// @phpstan-ignore argument.type, varTag.nativeType
/*
 * Prepare loop...
 */
$loop = new Loop($loop ?? new StreamSelectLoop());
BaseLoop::set($loop);
/*
 * Logging helpers...
 */
[$asyncStdOut, $asyncStdError] = match (\PHP_OS_FAMILY) {
    'Windows' => [null, null],
    default => [new WritableResourceStream(\STDOUT), new WritableResourceStream(\STDERR)],
};
$stdOut = new OutputWriter($loop, syncStream: \STDOUT, asyncStream: $asyncStdOut);
$stdErr = new OutputWriter($loop, syncStream: \STDERR, asyncStream: $asyncStdError);
$debug = static function (string $message) use ($verbose, $stdOut): void {
    if ($verbose) {
        $stdOut->write(date('Y-m-d H:i:s') . ' [DEBUG] ' . $message . \PHP_EOL);
    }
};
$info = static function (string $message) use ($silent, $quiet, $stdOut): void {
    if (!$quiet && !$silent) {
        $stdOut->write(date('Y-m-d H:i:s') . ' [INFO] ' . $message . \PHP_EOL);
    }
};
$error = static function (string $message) use ($silent, $stdErr): void {
    if (!$silent) {
        $stdErr->write(date('Y-m-d H:i:s') . ' [ERROR] ' . $message . \PHP_EOL);
    }
};
/*
 * Internal state...
 */
$tokenHash = substr(hash('xxh128', $refreshToken), 0, 7);
/** @var ?string $basePath */
$basePath ??= str_replace(['phar://', '/agent.phar/src'], '', __DIR__);
// @phpstan-ignore varTag.nativeType
$envoyerPath = preg_replace('#^(.*?)/releases/\d+/(.*)$#', '$1/current/$2', $basePath) ?? '';
if (is_file($envoyerPath . '/signature.txt') && realpath($envoyerPath) === $basePath) {
    $signaturePath = $envoyerPath . '/signature.txt';
} else {
    $signaturePath = $basePath . '/signature.txt';
}
$debug("Reading signature from [{$signaturePath}]");
$expectedSignature = @file_get_contents($signaturePath);
if ($expectedSignature === \false) {
    $error('Unable to read the signature');
    return;
}
$debug('Found signature [' . rtrim($expectedSignature) . ']');
$packageVersion = rtrim(file_get_contents($basePath . '/../../version.txt') ?: '');
/*
 * Initialize services...
 */
$clock ??= new Clock();
$browserFactory ??= new BrowserFactory();
$ingestDetailsBrowser = $browserFactory(connectionTimeout: $authenticationConnectionTimeout, timeout: $authenticationTimeout, headers: ['accept' => 'application/json', 'authorization' => "Bearer {$refreshToken}", 'content-type' => 'application/json', 'nightwatch-server' => $server, 'user-agent' => 'NightwatchAgent/' . $packageVersion], baseUrl: rtrim($baseUrl, '/'));
$ingestDetails = new IngestDetailsRepository(loop: $loop, browser: $ingestDetailsBrowser, clock: $clock, onAuthenticationSuccess: static fn(IngestDetails $ingestDetails, float $duration) => $info('Authentication successful [' . round($duration, 3) . 's]'), onAuthenticationError: static fn(string $message, float $duration) => $error('Authentication failed [' . round($duration, 3) . 's]: ' . $message), onUnderQuota: static function () use (&$ingest) {
    /** @var Ingest $ingest */
    $ingest->resumeIngestion();
});
$ingestBrowser = $browserFactory(connectionTimeout: $ingestConnectionTimeout, timeout: $ingestTimeout, headers: ['accept' => 'application/json', 'content-encoding' => 'gzip', 'content-type' => 'application/json', 'nightwatch-server' => $server, 'user-agent' => 'NightwatchAgent/' . $packageVersion]);
$ingest = new Ingest(loop: $loop, browser: $ingestBrowser, ingestDetails: $ingestDetails, clock: $clock, buffer: new StreamBuffer($maxBufferLength ?? 6000000), concurrentRequestLimit: 5, maxBufferDurationInSeconds: 10, onIngestSuccess: static fn(ResponseInterface $response, float $duration) => $info('Ingest successful [' . round($duration, 3) . 's]'), onIngestError: static fn(string $message, float $duration) => $error('Ingest failed [' . round($duration, 3) . 's]: ' . $message), onOverQuota: static fn(string $message, float $duration) => $error('Ingest attempted [' . round($duration, 3) . 's]: ' . $message));
$server = new Server(serverResolver: $serverResolver ?? static fn(): ServerInterface => new TcpServer($listenOn), tokenHash: $tokenHash, onServerStarted: static fn() => $info("Nightwatch agent initiated: Listening on [{$listenOn}]; Version [{$packageVersion}]"), onServerError: static fn(string $message) => $error("Server error: {$message}"), onConnectionError: static fn(string $message) => $error("Connection error: {$message}"), onPayloadReceived: $ingest->write(...), onInvalidPayloadVersion: static function () use ($info, $loop, $ingest) {
    $info('Incoming payload version has changed');
    $ingest->forceDigest()->finally(static function () use ($info, $loop) {
        $loop->stop();
        $info('Shutting down');
    });
}, onInvalidTokenHash: static fn() => $error('Incoming token hash mismatch! Check your application/agent configuration.'));
$checkSignature = new CheckSignature(loop: $loop, signaturePath: $signaturePath, expectedSignature: $expectedSignature, shutdownDelayInMinutes: 5, onCheckSignature: static function ($signature) use ($debug) {
    $debug('Signature checked: [' . rtrim($signature) . ']');
}, onShutdownInitiated: static function ($shuttingDownIn) use ($info) {
    $info('Agent signature changed: shutting down in ' . $shuttingDownIn . ' minutes');
}, onShutdown: static function () use ($info, $loop, $ingest) {
    $ingest->forceDigest()->finally(static function () use ($info, $loop) {
        $loop->stop();
        $info('Shutting down');
    });
});
/*
 * Get things rolling...
 */
$server->start();
$ingestDetails->hydrate();
$checkSignature->start();
$loop->run();
<?php

namespace NightwatchAgent_kden27khxA4QoEfj;

// When we run the agent within a Laravel application, the consuming Laravel
// application will have run its own autoloader. When this happens, Composer
// fills the `$GLOBALS['__composer_autoload_files']` variable with all
// autoloaded files, i.e., those listed under the `"files"` key in the
// `composer.json` of the project and its dependencies.
//
// Because we run the agent PHAR within the context of the consuming
// application we inherit the `$GLOBALS` variable from the outer scope. The
// PHAR is not an isolated environment.
//
// As Composer encounters each file to autoload it checks to ensure that
// Composer has not already required the file, by checking
// `$GLOBALS['__composer_autoload_files']`, based on the file's hash. If the
// agent and the consuming package require the same dependencies it is entirely
// possible that the agent's autoloader will mistakely think it has already
// autoloaded the shared dependencies files.
//
// To get around this, we temporarily empty the composer autoload files from
// from `$GLOBALS`, require the agent's autoloader, and then restore the global
// scope's autoloaded files in the `$GLOBALS` variable. This allows composer to
// autoload our depedencies files again.
$composerAutoloadFiles = $GLOBALS['__composer_autoload_files'] ?? [];
$GLOBALS['__composer_autoload_files'] = [];
/** @var \Composer\Autoload\ClassLoader $autoloader */
$autoloader = require __DIR__ . '/../vendor/autoload.php';
$GLOBALS['__composer_autoload_files'] = $composerAutoloadFiles;
// PHP lazily autoloads classes as they are encountered. A PHAR contains a
// virtual file system, to some degree, where each file exists as a line
// position within the PHAR. When running a PHAR, all classes in the PHAR are
// not loaded by default, they continue to be autoloaded as they are
// encountered. When the PHAR attempts to autoload a file, it will reach into
// the PHAR again, the PHAR will tell it the lines that the file exists on
// within the PHAR, and that "file" is then read into memory.
//
// When deploying, we replace the PHAR on the filesystem while the PHAR is
// still running.
//
// We then ask the in-memory running PHAR to shutdown. As it shutsdown, it
// wants classes it has not yet loaded. It attempts to read them from the new
// PHAR on disk and the line numbers do not match up. This results in strange
// syntax errors as it gets invalid "files".
//
// This results in shutdown errors that blast PHP code into the log files.
//
// To counteract this, we now eagerly load all known classes using the
// `class_exists` method. We cannot manually require the classes, as if the
// file has been required before it would be problematic. We also cannot use
// `require_once` as Composer does not use `require_once`.
//
// `class_exists` seems like a good way to have Composer do the autoloading
// legwork for us. It also successfully loads traits, interfaces, etc. The
// method simply returns `false` in those non-class cases, but the file is
// still autoloaded.
foreach ($autoloader->getClassMap() as $class => $path) {
    \class_exists($class);
}
<?php

// @generated by Humbug Box

$loader = (static function () {
    // Backup the autoloaded Composer files
    $existingComposerAutoloadFiles = isset($GLOBALS['__composer_autoload_files']) ? $GLOBALS['__composer_autoload_files'] : [];

    // autoload.php @generated by Composer

    if (PHP_VERSION_ID < 50600) {
        if (!headers_sent()) {
            header('HTTP/1.1 500 Internal Server Error');
        }
        $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
        if (!ini_get('display_errors')) {
            if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
                fwrite(STDERR, $err);
            } elseif (!headers_sent()) {
                echo $err;
            }
        }
        throw new RuntimeException($err);
    }

    require_once __DIR__ . '/composer/autoload_real.php';

    $loader = ComposerAutoloaderInitzUjV6thn8dELeOw6::getLoader();

    // Ensure InstalledVersions is available
    $installedVersionsPath = __DIR__.'/composer/InstalledVersions.php';
    if (file_exists($installedVersionsPath)) require_once $installedVersionsPath;

    // Restore the backup and ensure the excluded files are properly marked as loaded
    $GLOBALS['__composer_autoload_files'] = \array_merge(
        $existingComposerAutoloadFiles,
        \array_fill_keys([], true)
    );

    return $loader;
})();

// Function aliases. For more information see:
// https://github.com/humbug/php-scoper/blob/master/docs/further-reading.md#function-aliases
if (!function_exists('uv_poll_init_socket')) { function uv_poll_init_socket() { return \NightwatchAgent_kden27khxA4QoEfj\uv_poll_init_socket(...func_get_args()); } }

return $loader;
<?php

/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Composer\Autoload;

/**
 * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
 *
 *     $loader = new \Composer\Autoload\ClassLoader();
 *
 *     // register classes with namespaces
 *     $loader->add('Symfony\Component', __DIR__.'/component');
 *     $loader->add('Symfony',           __DIR__.'/framework');
 *
 *     // activate the autoloader
 *     $loader->register();
 *
 *     // to enable searching the include path (eg. for PEAR packages)
 *     $loader->setUseIncludePath(true);
 *
 * In this example, if you try to use a class in the Symfony\Component
 * namespace or one of its children (Symfony\Component\Console for instance),
 * the autoloader will first look for the class under the component/
 * directory, and it will then fallback to the framework/ directory if not
 * found before giving up.
 *
 * This class is loosely based on the Symfony UniversalClassLoader.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @see    https://www.php-fig.org/psr/psr-0/
 * @see    https://www.php-fig.org/psr/psr-4/
 */
class ClassLoader
{
    /** @var \Closure(string):void */
    private static $includeFile;

    /** @var string|null */
    private $vendorDir;

    // PSR-4
    /**
     * @var array<string, array<string, int>>
     */
    private $prefixLengthsPsr4 = array();
    /**
     * @var array<string, list<string>>
     */
    private $prefixDirsPsr4 = array();
    /**
     * @var list<string>
     */
    private $fallbackDirsPsr4 = array();

    // PSR-0
    /**
     * List of PSR-0 prefixes
     *
     * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
     *
     * @var array<string, array<string, list<string>>>
     */
    private $prefixesPsr0 = array();
    /**
     * @var list<string>
     */
    private $fallbackDirsPsr0 = array();

    /** @var bool */
    private $useIncludePath = false;

    /**
     * @var array<string, string>
     */
    private $classMap = array();

    /** @var bool */
    private $classMapAuthoritative = false;

    /**
     * @var array<string, bool>
     */
    private $missingClasses = array();

    /** @var string|null */
    private $apcuPrefix;

    /**
     * @var array<string, self>
     */
    private static $registeredLoaders = array();

    /**
     * @param string|null $vendorDir
     */
    public function __construct($vendorDir = null)
    {
        $this->vendorDir = $vendorDir;
        self::initializeIncludeClosure();
    }

    /**
     * @return array<string, list<string>>
     */
    public function getPrefixes()
    {
        if (!empty($this->prefixesPsr0)) {
            return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
        }

        return array();
    }

    /**
     * @return array<string, list<string>>
     */
    public function getPrefixesPsr4()
    {
        return $this->prefixDirsPsr4;
    }

    /**
     * @return list<string>
     */
    public function getFallbackDirs()
    {
        return $this->fallbackDirsPsr0;
    }

    /**
     * @return list<string>
     */
    public function getFallbackDirsPsr4()
    {
        return $this->fallbackDirsPsr4;
    }

    /**
     * @return array<string, string> Array of classname => path
     */
    public function getClassMap()
    {
        return $this->classMap;
    }

    /**
     * @param array<string, string> $classMap Class to filename map
     *
     * @return void
     */
    public function addClassMap(array $classMap)
    {
        if ($this->classMap) {
            $this->classMap = array_merge($this->classMap, $classMap);
        } else {
            $this->classMap = $classMap;
        }
    }

    /**
     * Registers a set of PSR-0 directories for a given prefix, either
     * appending or prepending to the ones previously set for this prefix.
     *
     * @param string              $prefix  The prefix
     * @param list<string>|string $paths   The PSR-0 root directories
     * @param bool                $prepend Whether to prepend the directories
     *
     * @return void
     */
    public function add($prefix, $paths, $prepend = false)
    {
        $paths = (array) $paths;
        if (!$prefix) {
            if ($prepend) {
                $this->fallbackDirsPsr0 = array_merge(
                    $paths,
                    $this->fallbackDirsPsr0
                );
            } else {
                $this->fallbackDirsPsr0 = array_merge(
                    $this->fallbackDirsPsr0,
                    $paths
                );
            }

            return;
        }

        $first = $prefix[0];
        if (!isset($this->prefixesPsr0[$first][$prefix])) {
            $this->prefixesPsr0[$first][$prefix] = $paths;

            return;
        }
        if ($prepend) {
            $this->prefixesPsr0[$first][$prefix] = array_merge(
                $paths,
                $this->prefixesPsr0[$first][$prefix]
            );
        } else {
            $this->prefixesPsr0[$first][$prefix] = array_merge(
                $this->prefixesPsr0[$first][$prefix],
                $paths
            );
        }
    }

    /**
     * Registers a set of PSR-4 directories for a given namespace, either
     * appending or prepending to the ones previously set for this namespace.
     *
     * @param string              $prefix  The prefix/namespace, with trailing '\\'
     * @param list<string>|string $paths   The PSR-4 base directories
     * @param bool                $prepend Whether to prepend the directories
     *
     * @throws \InvalidArgumentException
     *
     * @return void
     */
    public function addPsr4($prefix, $paths, $prepend = false)
    {
        $paths = (array) $paths;
        if (!$prefix) {
            // Register directories for the root namespace.
            if ($prepend) {
                $this->fallbackDirsPsr4 = array_merge(
                    $paths,
                    $this->fallbackDirsPsr4
                );
            } else {
                $this->fallbackDirsPsr4 = array_merge(
                    $this->fallbackDirsPsr4,
                    $paths
                );
            }
        } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
            // Register directories for a new namespace.
            $length = strlen($prefix);
            if ('\\' !== $prefix[$length - 1]) {
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
            }
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
            $this->prefixDirsPsr4[$prefix] = $paths;
        } elseif ($prepend) {
            // Prepend directories for an already registered namespace.
            $this->prefixDirsPsr4[$prefix] = array_merge(
                $paths,
                $this->prefixDirsPsr4[$prefix]
            );
        } else {
            // Append directories for an already registered namespace.
            $this->prefixDirsPsr4[$prefix] = array_merge(
                $this->prefixDirsPsr4[$prefix],
                $paths
            );
        }
    }

    /**
     * Registers a set of PSR-0 directories for a given prefix,
     * replacing any others previously set for this prefix.
     *
     * @param string              $prefix The prefix
     * @param list<string>|string $paths  The PSR-0 base directories
     *
     * @return void
     */
    public function set($prefix, $paths)
    {
        if (!$prefix) {
            $this->fallbackDirsPsr0 = (array) $paths;
        } else {
            $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
        }
    }

    /**
     * Registers a set of PSR-4 directories for a given namespace,
     * replacing any others previously set for this namespace.
     *
     * @param string              $prefix The prefix/namespace, with trailing '\\'
     * @param list<string>|string $paths  The PSR-4 base directories
     *
     * @throws \InvalidArgumentException
     *
     * @return void
     */
    public function setPsr4($prefix, $paths)
    {
        if (!$prefix) {
            $this->fallbackDirsPsr4 = (array) $paths;
        } else {
            $length = strlen($prefix);
            if ('\\' !== $prefix[$length - 1]) {
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
            }
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
            $this->prefixDirsPsr4[$prefix] = (array) $paths;
        }
    }

    /**
     * Turns on searching the include path for class files.
     *
     * @param bool $useIncludePath
     *
     * @return void
     */
    public function setUseIncludePath($useIncludePath)
    {
        $this->useIncludePath = $useIncludePath;
    }

    /**
     * Can be used to check if the autoloader uses the include path to check
     * for classes.
     *
     * @return bool
     */
    public function getUseIncludePath()
    {
        return $this->useIncludePath;
    }

    /**
     * Turns off searching the prefix and fallback directories for classes
     * that have not been registered with the class map.
     *
     * @param bool $classMapAuthoritative
     *
     * @return void
     */
    public function setClassMapAuthoritative($classMapAuthoritative)
    {
        $this->classMapAuthoritative = $classMapAuthoritative;
    }

    /**
     * Should class lookup fail if not found in the current class map?
     *
     * @return bool
     */
    public function isClassMapAuthoritative()
    {
        return $this->classMapAuthoritative;
    }

    /**
     * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
     *
     * @param string|null $apcuPrefix
     *
     * @return void
     */
    public function setApcuPrefix($apcuPrefix)
    {
        $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
    }

    /**
     * The APCu prefix in use, or null if APCu caching is not enabled.
     *
     * @return string|null
     */
    public function getApcuPrefix()
    {
        return $this->apcuPrefix;
    }

    /**
     * Registers this instance as an autoloader.
     *
     * @param bool $prepend Whether to prepend the autoloader or not
     *
     * @return void
     */
    public function register($prepend = false)
    {
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);

        if (null === $this->vendorDir) {
            return;
        }

        if ($prepend) {
            self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
        } else {
            unset(self::$registeredLoaders[$this->vendorDir]);
            self::$registeredLoaders[$this->vendorDir] = $this;
        }
    }

    /**
     * Unregisters this instance as an autoloader.
     *
     * @return void
     */
    public function unregister()
    {
        spl_autoload_unregister(array($this, 'loadClass'));

        if (null !== $this->vendorDir) {
            unset(self::$registeredLoaders[$this->vendorDir]);
        }
    }

    /**
     * Loads the given class or interface.
     *
     * @param  string    $class The name of the class
     * @return true|null True if loaded, null otherwise
     */
    public function loadClass($class)
    {
        if ($file = $this->findFile($class)) {
            $includeFile = self::$includeFile;
            $includeFile($file);

            return true;
        }

        return null;
    }

    /**
     * Finds the path to the file where the class is defined.
     *
     * @param string $class The name of the class
     *
     * @return string|false The path if found, false otherwise
     */
    public function findFile($class)
    {
        // class map lookup
        if (isset($this->classMap[$class])) {
            return $this->classMap[$class];
        }
        if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
            return false;
        }
        if (null !== $this->apcuPrefix) {
            $file = apcu_fetch($this->apcuPrefix.$class, $hit);
            if ($hit) {
                return $file;
            }
        }

        $file = $this->findFileWithExtension($class, '.php');

        // Search for Hack files if we are running on HHVM
        if (false === $file && defined('HHVM_VERSION')) {
            $file = $this->findFileWithExtension($class, '.hh');
        }

        if (null !== $this->apcuPrefix) {
            apcu_add($this->apcuPrefix.$class, $file);
        }

        if (false === $file) {
            // Remember that this class does not exist.
            $this->missingClasses[$class] = true;
        }

        return $file;
    }

    /**
     * Returns the currently registered loaders keyed by their corresponding vendor directories.
     *
     * @return array<string, self>
     */
    public static function getRegisteredLoaders()
    {
        return self::$registeredLoaders;
    }

    /**
     * @param  string       $class
     * @param  string       $ext
     * @return string|false
     */
    private function findFileWithExtension($class, $ext)
    {
        // PSR-4 lookup
        $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;

        $first = $class[0];
        if (isset($this->prefixLengthsPsr4[$first])) {
            $subPath = $class;
            while (false !== $lastPos = strrpos($subPath, '\\')) {
                $subPath = substr($subPath, 0, $lastPos);
                $search = $subPath . '\\';
                if (isset($this->prefixDirsPsr4[$search])) {
                    $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
                    foreach ($this->prefixDirsPsr4[$search] as $dir) {
                        if (file_exists($file = $dir . $pathEnd)) {
                            return $file;
                        }
                    }
                }
            }
        }

        // PSR-4 fallback dirs
        foreach ($this->fallbackDirsPsr4 as $dir) {
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
                return $file;
            }
        }

        // PSR-0 lookup
        if (false !== $pos = strrpos($class, '\\')) {
            // namespaced class name
            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
                . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
        } else {
            // PEAR-like class name
            $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
        }

        if (isset($this->prefixesPsr0[$first])) {
            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
                if (0 === strpos($class, $prefix)) {
                    foreach ($dirs as $dir) {
                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
                            return $file;
                        }
                    }
                }
            }
        }

        // PSR-0 fallback dirs
        foreach ($this->fallbackDirsPsr0 as $dir) {
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
                return $file;
            }
        }

        // PSR-0 include paths.
        if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
            return $file;
        }

        return false;
    }

    /**
     * @return void
     */
    private static function initializeIncludeClosure()
    {
        if (self::$includeFile !== null) {
            return;
        }

        /**
         * Scope isolated include.
         *
         * Prevents access to $this/self from included files.
         *
         * @param  string $file
         * @return void
         */
        self::$includeFile = \Closure::bind(static function($file) {
            include $file;
        }, null, null);
    }
}
<?php

/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace NightwatchAgent_kden27khxA4QoEfj\Composer;

use NightwatchAgent_kden27khxA4QoEfj\Composer\Autoload\ClassLoader;
use NightwatchAgent_kden27khxA4QoEfj\Composer\Semver\VersionParser;
/**
 * This class is copied in every Composer installed project and available to all
 *
 * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
 *
 * To require its presence, you can require `composer-runtime-api ^2.0`
 *
 * @final
 */

if (! class_exists(InstalledVersions::class, autoload: false)) {
class InstalledVersions
{
    /**
     * @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to
     * @internal
     */
    private static $selfDir = null;
    /**
     * @var mixed[]|null
     * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
     */
    private static $installed;
    /**
     * @var bool
     */
    private static $installedIsLocalDir;
    /**
     * @var bool|null
     */
    private static $canGetVendors;
    /**
     * @var array[]
     * @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
     */
    private static $installedByVendor = array();
    /**
     * Returns a list of all package names which are present, either by being installed, replaced or provided
     *
     * @return string[]
     * @psalm-return list<string>
     */
    public static function getInstalledPackages()
    {
        $packages = array();
        foreach (self::getInstalled() as $installed) {
            $packages[] = array_keys($installed['versions']);
        }
        if (1 === \count($packages)) {
            return $packages[0];
        }
        return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
    }
    /**
     * Returns a list of all package names with a specific type e.g. 'library'
     *
     * @param  string   $type
     * @return string[]
     * @psalm-return list<string>
     */
    public static function getInstalledPackagesByType($type)
    {
        $packagesByType = array();
        foreach (self::getInstalled() as $installed) {
            foreach ($installed['versions'] as $name => $package) {
                if (isset($package['type']) && $package['type'] === $type) {
                    $packagesByType[] = $name;
                }
            }
        }
        return $packagesByType;
    }
    /**
     * Checks whether the given package is installed
     *
     * This also returns true if the package name is provided or replaced by another package
     *
     * @param  string $packageName
     * @param  bool   $includeDevRequirements
     * @return bool
     */
    public static function isInstalled($packageName, $includeDevRequirements = \true)
    {
        foreach (self::getInstalled() as $installed) {
            if (isset($installed['versions'][$packageName])) {
                return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === \false;
            }
        }
        return \false;
    }
    /**
     * Checks whether the given package satisfies a version constraint
     *
     * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
     *
     *   Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
     *
     * @param  VersionParser $parser      Install composer/semver to have access to this class and functionality
     * @param  string        $packageName
     * @param  string|null   $constraint  A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
     * @return bool
     */
    public static function satisfies(VersionParser $parser, $packageName, $constraint)
    {
        $constraint = $parser->parseConstraints((string) $constraint);
        $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
        return $provided->matches($constraint);
    }
    /**
     * Returns a version constraint representing all the range(s) which are installed for a given package
     *
     * It is easier to use this via isInstalled() with the $constraint argument if you need to check
     * whether a given version of a package is installed, and not just whether it exists
     *
     * @param  string $packageName
     * @return string Version constraint usable with composer/semver
     */
    public static function getVersionRanges($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }
            $ranges = array();
            if (isset($installed['versions'][$packageName]['pretty_version'])) {
                $ranges[] = $installed['versions'][$packageName]['pretty_version'];
            }
            if (array_key_exists('aliases', $installed['versions'][$packageName])) {
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
            }
            if (array_key_exists('replaced', $installed['versions'][$packageName])) {
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
            }
            if (array_key_exists('provided', $installed['versions'][$packageName])) {
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
            }
            return implode(' || ', $ranges);
        }
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }
    /**
     * @param  string      $packageName
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
     */
    public static function getVersion($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }
            if (!isset($installed['versions'][$packageName]['version'])) {
                return null;
            }
            return $installed['versions'][$packageName]['version'];
        }
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }
    /**
     * @param  string      $packageName
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
     */
    public static function getPrettyVersion($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }
            if (!isset($installed['versions'][$packageName]['pretty_version'])) {
                return null;
            }
            return $installed['versions'][$packageName]['pretty_version'];
        }
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }
    /**
     * @param  string      $packageName
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
     */
    public static function getReference($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }
            if (!isset($installed['versions'][$packageName]['reference'])) {
                return null;
            }
            return $installed['versions'][$packageName]['reference'];
        }
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }
    /**
     * @param  string      $packageName
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
     */
    public static function getInstallPath($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }
            return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
        }
        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }
    /**
     * @return array
     * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
     */
    public static function getRootPackage()
    {
        $installed = self::getInstalled();
        return $installed[0]['root'];
    }
    /**
     * Returns the raw installed.php data for custom implementations
     *
     * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
     * @return array[]
     * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
     */
    public static function getRawData()
    {
        @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', \E_USER_DEPRECATED);
        if (null === self::$installed) {
            // only require the installed.php file if this file is loaded from its dumped location,
            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
            if (substr(__DIR__, -8, 1) !== 'C') {
                self::$installed = include __DIR__ . '/installed.php';
            } else {
                self::$installed = array();
            }
        }
        return self::$installed;
    }
    /**
     * Returns the raw data of all installed.php which are currently loaded for custom implementations
     *
     * @return array[]
     * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
     */
    public static function getAllRawData()
    {
        return self::getInstalled();
    }
    /**
     * Lets you reload the static array from another file
     *
     * This is only useful for complex integrations in which a project needs to use
     * this class but then also needs to execute another project's autoloader in process,
     * and wants to ensure both projects have access to their version of installed.php.
     *
     * A typical case would be PHPUnit, where it would need to make sure it reads all
     * the data it needs from this class, then call reload() with
     * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
     * the project in which it runs can then also use this class safely, without
     * interference between PHPUnit's dependencies and the project's dependencies.
     *
     * @param  array[] $data A vendor/composer/installed.php data set
     * @return void
     *
     * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
     */
    public static function reload($data)
    {
        self::$installed = $data;
        self::$installedByVendor = array();
        // when using reload, we disable the duplicate protection to ensure that self::$installed data is
        // always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not,
        // so we have to assume it does not, and that may result in duplicate data being returned when listing
        // all installed packages for example
        self::$installedIsLocalDir = \false;
    }
    /**
     * @return string
     */
    private static function getSelfDir()
    {
        if (self::$selfDir === null) {
            self::$selfDir = strtr(__DIR__, '\\', '/');
        }
        return self::$selfDir;
    }
    /**
     * @return array[]
     * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
     */
    private static function getInstalled()
    {
        if (null === self::$canGetVendors) {
            self::$canGetVendors = method_exists('NightwatchAgent_kden27khxA4QoEfj\Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
        }
        $installed = array();
        $copiedLocalDir = \false;
        if (self::$canGetVendors) {
            $selfDir = self::getSelfDir();
            foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
                $vendorDir = strtr($vendorDir, '\\', '/');
                if (isset(self::$installedByVendor[$vendorDir])) {
                    $installed[] = self::$installedByVendor[$vendorDir];
                } elseif (is_file($vendorDir . '/composer/installed.php')) {
                    /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
                    $required = require $vendorDir . '/composer/installed.php';
                    self::$installedByVendor[$vendorDir] = $required;
                    $installed[] = $required;
                    if (self::$installed === null && $vendorDir . '/composer' === $selfDir) {
                        self::$installed = $required;
                        self::$installedIsLocalDir = \true;
                    }
                }
                if (self::$installedIsLocalDir && $vendorDir . '/composer' === $selfDir) {
                    $copiedLocalDir = \true;
                }
            }
        }
        if (null === self::$installed) {
            // only require the installed.php file if this file is loaded from its dumped location,
            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
            if (substr(__DIR__, -8, 1) !== 'C') {
                /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
                $required = require __DIR__ . '/installed.php';
                self::$installed = $required;
            } else {
                self::$installed = array();
            }
        }
        if (self::$installed !== array() && !$copiedLocalDir) {
            $installed[] = self::$installed;
        }
        return $installed;
    }
}
}

Copyright (c) Nils Adermann, Jordi Boggiano

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

<?php

// autoload_classmap.php @generated by Composer

$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);

return array(
    'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Evenement\\EventEmitter' => $vendorDir . '/evenement/evenement/src/EventEmitter.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Evenement\\EventEmitterInterface' => $vendorDir . '/evenement/evenement/src/EventEmitterInterface.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Evenement\\EventEmitterTrait' => $vendorDir . '/evenement/evenement/src/EventEmitterTrait.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Fig\\Http\\Message\\RequestMethodInterface' => $vendorDir . '/fig/http-message-util/src/RequestMethodInterface.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Fig\\Http\\Message\\StatusCodeInterface' => $vendorDir . '/fig/http-message-util/src/StatusCodeInterface.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\Browser' => $baseDir . '/src/Browser.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\CheckSignature' => $baseDir . '/src/CheckSignature.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\Clock' => $baseDir . '/src/Clock.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\Contracts\\Browser' => $baseDir . '/src/Contracts/Browser.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\Contracts\\Clock' => $baseDir . '/src/Contracts/Clock.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\Factories\\BrowserFactory' => $baseDir . '/src/Factories/BrowserFactory.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\Ingest' => $baseDir . '/src/Ingest.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\IngestDetails' => $baseDir . '/src/IngestDetails.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\IngestDetailsRepository' => $baseDir . '/src/IngestDetailsRepository.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\Loop' => $baseDir . '/src/Loop.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\NullBuffer' => $baseDir . '/src/NullBuffer.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\OutputWriter' => $baseDir . '/src/OutputWriter.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\Payload' => $baseDir . '/src/Payload.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\Server' => $baseDir . '/src/Server.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\StreamBuffer' => $baseDir . '/src/StreamBuffer.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Psr\\Http\\Message\\MessageInterface' => $vendorDir . '/psr/http-message/src/MessageInterface.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Psr\\Http\\Message\\RequestInterface' => $vendorDir . '/psr/http-message/src/RequestInterface.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Psr\\Http\\Message\\ResponseInterface' => $vendorDir . '/psr/http-message/src/ResponseInterface.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Psr\\Http\\Message\\ServerRequestInterface' => $vendorDir . '/psr/http-message/src/ServerRequestInterface.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Psr\\Http\\Message\\StreamInterface' => $vendorDir . '/psr/http-message/src/StreamInterface.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Psr\\Http\\Message\\UploadedFileInterface' => $vendorDir . '/psr/http-message/src/UploadedFileInterface.php',
    'NightwatchAgent_kden27khxA4QoEfj\\Psr\\Http\\Message\\UriInterface' => $vendorDir . '/psr/http-message/src/UriInterface.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Cache\\ArrayCache' => $vendorDir . '/react/cache/src/ArrayCache.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Cache\\CacheInterface' => $vendorDir . '/react/cache/src/CacheInterface.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\BadServerException' => $vendorDir . '/react/dns/src/BadServerException.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Config\\Config' => $vendorDir . '/react/dns/src/Config/Config.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Config\\HostsFile' => $vendorDir . '/react/dns/src/Config/HostsFile.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Model\\Message' => $vendorDir . '/react/dns/src/Model/Message.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Model\\Record' => $vendorDir . '/react/dns/src/Model/Record.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Protocol\\BinaryDumper' => $vendorDir . '/react/dns/src/Protocol/BinaryDumper.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Protocol\\Parser' => $vendorDir . '/react/dns/src/Protocol/Parser.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\CachingExecutor' => $vendorDir . '/react/dns/src/Query/CachingExecutor.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\CancellationException' => $vendorDir . '/react/dns/src/Query/CancellationException.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\CoopExecutor' => $vendorDir . '/react/dns/src/Query/CoopExecutor.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\ExecutorInterface' => $vendorDir . '/react/dns/src/Query/ExecutorInterface.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\FallbackExecutor' => $vendorDir . '/react/dns/src/Query/FallbackExecutor.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\HostsFileExecutor' => $vendorDir . '/react/dns/src/Query/HostsFileExecutor.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\Query' => $vendorDir . '/react/dns/src/Query/Query.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\RetryExecutor' => $vendorDir . '/react/dns/src/Query/RetryExecutor.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\SelectiveTransportExecutor' => $vendorDir . '/react/dns/src/Query/SelectiveTransportExecutor.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\TcpTransportExecutor' => $vendorDir . '/react/dns/src/Query/TcpTransportExecutor.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\TimeoutException' => $vendorDir . '/react/dns/src/Query/TimeoutException.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\TimeoutExecutor' => $vendorDir . '/react/dns/src/Query/TimeoutExecutor.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\UdpTransportExecutor' => $vendorDir . '/react/dns/src/Query/UdpTransportExecutor.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\RecordNotFoundException' => $vendorDir . '/react/dns/src/RecordNotFoundException.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Resolver\\Factory' => $vendorDir . '/react/dns/src/Resolver/Factory.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Resolver\\Resolver' => $vendorDir . '/react/dns/src/Resolver/Resolver.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Resolver\\ResolverInterface' => $vendorDir . '/react/dns/src/Resolver/ResolverInterface.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\ExtEvLoop' => $vendorDir . '/react/event-loop/src/ExtEvLoop.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\ExtEventLoop' => $vendorDir . '/react/event-loop/src/ExtEventLoop.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\ExtLibevLoop' => $vendorDir . '/react/event-loop/src/ExtLibevLoop.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\ExtLibeventLoop' => $vendorDir . '/react/event-loop/src/ExtLibeventLoop.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\ExtUvLoop' => $vendorDir . '/react/event-loop/src/ExtUvLoop.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\Factory' => $vendorDir . '/react/event-loop/src/Factory.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\Loop' => $vendorDir . '/react/event-loop/src/Loop.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\LoopInterface' => $vendorDir . '/react/event-loop/src/LoopInterface.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\SignalsHandler' => $vendorDir . '/react/event-loop/src/SignalsHandler.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\StreamSelectLoop' => $vendorDir . '/react/event-loop/src/StreamSelectLoop.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\Tick\\FutureTickQueue' => $vendorDir . '/react/event-loop/src/Tick/FutureTickQueue.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\TimerInterface' => $vendorDir . '/react/event-loop/src/TimerInterface.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\Timer\\Timer' => $vendorDir . '/react/event-loop/src/Timer/Timer.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\Timer\\Timers' => $vendorDir . '/react/event-loop/src/Timer/Timers.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Browser' => $vendorDir . '/react/http/src/Browser.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Client\\Client' => $vendorDir . '/react/http/src/Client/Client.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\HttpServer' => $vendorDir . '/react/http/src/HttpServer.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\AbstractMessage' => $vendorDir . '/react/http/src/Io/AbstractMessage.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\AbstractRequest' => $vendorDir . '/react/http/src/Io/AbstractRequest.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\BufferedBody' => $vendorDir . '/react/http/src/Io/BufferedBody.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\ChunkedDecoder' => $vendorDir . '/react/http/src/Io/ChunkedDecoder.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\ChunkedEncoder' => $vendorDir . '/react/http/src/Io/ChunkedEncoder.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\ClientConnectionManager' => $vendorDir . '/react/http/src/Io/ClientConnectionManager.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\ClientRequestState' => $vendorDir . '/react/http/src/Io/ClientRequestState.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\ClientRequestStream' => $vendorDir . '/react/http/src/Io/ClientRequestStream.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\Clock' => $vendorDir . '/react/http/src/Io/Clock.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\CloseProtectionStream' => $vendorDir . '/react/http/src/Io/CloseProtectionStream.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\EmptyBodyStream' => $vendorDir . '/react/http/src/Io/EmptyBodyStream.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\HttpBodyStream' => $vendorDir . '/react/http/src/Io/HttpBodyStream.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\IniUtil' => $vendorDir . '/react/http/src/Io/IniUtil.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\LengthLimitedStream' => $vendorDir . '/react/http/src/Io/LengthLimitedStream.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\MiddlewareRunner' => $vendorDir . '/react/http/src/Io/MiddlewareRunner.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\MultipartParser' => $vendorDir . '/react/http/src/Io/MultipartParser.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\PauseBufferStream' => $vendorDir . '/react/http/src/Io/PauseBufferStream.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\ReadableBodyStream' => $vendorDir . '/react/http/src/Io/ReadableBodyStream.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\RequestHeaderParser' => $vendorDir . '/react/http/src/Io/RequestHeaderParser.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\Sender' => $vendorDir . '/react/http/src/Io/Sender.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\StreamingServer' => $vendorDir . '/react/http/src/Io/StreamingServer.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\Transaction' => $vendorDir . '/react/http/src/Io/Transaction.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\UploadedFile' => $vendorDir . '/react/http/src/Io/UploadedFile.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Message\\Request' => $vendorDir . '/react/http/src/Message/Request.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Message\\Response' => $vendorDir . '/react/http/src/Message/Response.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Message\\ResponseException' => $vendorDir . '/react/http/src/Message/ResponseException.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Message\\ServerRequest' => $vendorDir . '/react/http/src/Message/ServerRequest.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Message\\Uri' => $vendorDir . '/react/http/src/Message/Uri.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Middleware\\LimitConcurrentRequestsMiddleware' => $vendorDir . '/react/http/src/Middleware/LimitConcurrentRequestsMiddleware.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Middleware\\RequestBodyBufferMiddleware' => $vendorDir . '/react/http/src/Middleware/RequestBodyBufferMiddleware.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Middleware\\RequestBodyParserMiddleware' => $vendorDir . '/react/http/src/Middleware/RequestBodyParserMiddleware.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Middleware\\StreamingRequestMiddleware' => $vendorDir . '/react/http/src/Middleware/StreamingRequestMiddleware.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Server' => $vendorDir . '/react/http/src/Server.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Promise\\Deferred' => $vendorDir . '/react/promise/src/Deferred.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Promise\\Exception\\CompositeException' => $vendorDir . '/react/promise/src/Exception/CompositeException.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Promise\\Exception\\LengthException' => $vendorDir . '/react/promise/src/Exception/LengthException.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Promise\\Internal\\CancellationQueue' => $vendorDir . '/react/promise/src/Internal/CancellationQueue.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Promise\\Internal\\FulfilledPromise' => $vendorDir . '/react/promise/src/Internal/FulfilledPromise.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Promise\\Internal\\RejectedPromise' => $vendorDir . '/react/promise/src/Internal/RejectedPromise.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Promise\\Promise' => $vendorDir . '/react/promise/src/Promise.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Promise\\PromiseInterface' => $vendorDir . '/react/promise/src/PromiseInterface.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\Connection' => $vendorDir . '/react/socket/src/Connection.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\ConnectionInterface' => $vendorDir . '/react/socket/src/ConnectionInterface.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\Connector' => $vendorDir . '/react/socket/src/Connector.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\ConnectorInterface' => $vendorDir . '/react/socket/src/ConnectorInterface.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\DnsConnector' => $vendorDir . '/react/socket/src/DnsConnector.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\FdServer' => $vendorDir . '/react/socket/src/FdServer.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\FixedUriConnector' => $vendorDir . '/react/socket/src/FixedUriConnector.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\HappyEyeBallsConnectionBuilder' => $vendorDir . '/react/socket/src/HappyEyeBallsConnectionBuilder.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\HappyEyeBallsConnector' => $vendorDir . '/react/socket/src/HappyEyeBallsConnector.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\LimitingServer' => $vendorDir . '/react/socket/src/LimitingServer.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\SecureConnector' => $vendorDir . '/react/socket/src/SecureConnector.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\SecureServer' => $vendorDir . '/react/socket/src/SecureServer.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\Server' => $vendorDir . '/react/socket/src/Server.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\ServerInterface' => $vendorDir . '/react/socket/src/ServerInterface.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\SocketServer' => $vendorDir . '/react/socket/src/SocketServer.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\StreamEncryption' => $vendorDir . '/react/socket/src/StreamEncryption.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\TcpConnector' => $vendorDir . '/react/socket/src/TcpConnector.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\TcpServer' => $vendorDir . '/react/socket/src/TcpServer.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\TimeoutConnector' => $vendorDir . '/react/socket/src/TimeoutConnector.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\UnixConnector' => $vendorDir . '/react/socket/src/UnixConnector.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\UnixServer' => $vendorDir . '/react/socket/src/UnixServer.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Stream\\CompositeStream' => $vendorDir . '/react/stream/src/CompositeStream.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Stream\\DuplexResourceStream' => $vendorDir . '/react/stream/src/DuplexResourceStream.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Stream\\DuplexStreamInterface' => $vendorDir . '/react/stream/src/DuplexStreamInterface.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Stream\\ReadableResourceStream' => $vendorDir . '/react/stream/src/ReadableResourceStream.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Stream\\ReadableStreamInterface' => $vendorDir . '/react/stream/src/ReadableStreamInterface.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Stream\\ThroughStream' => $vendorDir . '/react/stream/src/ThroughStream.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Stream\\Util' => $vendorDir . '/react/stream/src/Util.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Stream\\WritableResourceStream' => $vendorDir . '/react/stream/src/WritableResourceStream.php',
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Stream\\WritableStreamInterface' => $vendorDir . '/react/stream/src/WritableStreamInterface.php',
);
<?php

// autoload_files.php @generated by Composer

$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);

return array(
    'ad155f8f1cf0d418fe49e248db8c661b' => $vendorDir . '/react/promise/src/functions_include.php',
    'f4e1d0315f06d2ad971577299b168562' => $baseDir . '/helpers.php',
);
<?php

// autoload_namespaces.php @generated by Composer

$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);

return array(
);
<?php

// autoload_psr4.php @generated by Composer

$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);

return array(
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Stream\\' => array($vendorDir . '/react/stream/src'),
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\' => array($vendorDir . '/react/socket/src'),
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Promise\\' => array($vendorDir . '/react/promise/src'),
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\' => array($vendorDir . '/react/http/src'),
    'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\' => array($vendorDir . '/react/event-loop/src'),
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\' => array($vendorDir . '/react/dns/src'),
    'NightwatchAgent_kden27khxA4QoEfj\\React\\Cache\\' => array($vendorDir . '/react/cache/src'),
    'NightwatchAgent_kden27khxA4QoEfj\\Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
    'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\' => array($baseDir . '/src'),
    'NightwatchAgent_kden27khxA4QoEfj\\Fig\\Http\\Message\\' => array($vendorDir . '/fig/http-message-util/src'),
    'NightwatchAgent_kden27khxA4QoEfj\\Evenement\\' => array($vendorDir . '/evenement/evenement/src'),
);
<?php

// autoload_real.php @generated by Composer

class ComposerAutoloaderInitzUjV6thn8dELeOw6
{
    private static $loader;

    public static function loadClassLoader($class)
    {
        if ('Composer\Autoload\ClassLoader' === $class) {
            require __DIR__ . '/ClassLoader.php';
        }
    }

    /**
     * @return \Composer\Autoload\ClassLoader
     */
    public static function getLoader()
    {
        if (null !== self::$loader) {
            return self::$loader;
        }

        require __DIR__ . '/platform_check.php';

        spl_autoload_register(array('ComposerAutoloaderInitzUjV6thn8dELeOw6', 'loadClassLoader'), true, true);
        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
        spl_autoload_unregister(array('ComposerAutoloaderInitzUjV6thn8dELeOw6', 'loadClassLoader'));

        require __DIR__ . '/autoload_static.php';
        call_user_func(\Composer\Autoload\ComposerStaticInitzUjV6thn8dELeOw6::getInitializer($loader));

        $loader->setClassMapAuthoritative(true);
        $loader->register(true);

        $filesToLoad = \Composer\Autoload\ComposerStaticInitzUjV6thn8dELeOw6::$files;
        $requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
            if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
                $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;

                require $file;
            }
        }, null, null);
        foreach ($filesToLoad as $fileIdentifier => $file) {
            $requireFile($fileIdentifier, $file);
        }

        return $loader;
    }
}
<?php

// autoload_static.php @generated by Composer

namespace Composer\Autoload;

class ComposerStaticInitzUjV6thn8dELeOw6
{
    public static $files = array (
        'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
        'f4e1d0315f06d2ad971577299b168562' => __DIR__ . '/../..' . '/helpers.php',
    );

    public static $prefixLengthsPsr4 = array (
        'N' => 
        array (
            'NightwatchAgent_kden27khxA4QoEfj\\React\\Stream\\' => 46,
            'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\' => 46,
            'NightwatchAgent_kden27khxA4QoEfj\\React\\Promise\\' => 47,
            'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\' => 44,
            'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\' => 49,
            'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\' => 43,
            'NightwatchAgent_kden27khxA4QoEfj\\React\\Cache\\' => 45,
            'NightwatchAgent_kden27khxA4QoEfj\\Psr\\Http\\Message\\' => 50,
            'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\' => 57,
            'NightwatchAgent_kden27khxA4QoEfj\\Fig\\Http\\Message\\' => 50,
            'NightwatchAgent_kden27khxA4QoEfj\\Evenement\\' => 43,
        ),
    );

    public static $prefixDirsPsr4 = array (
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Stream\\' => 
        array (
            0 => __DIR__ . '/..' . '/react/stream/src',
        ),
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\' => 
        array (
            0 => __DIR__ . '/..' . '/react/socket/src',
        ),
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Promise\\' => 
        array (
            0 => __DIR__ . '/..' . '/react/promise/src',
        ),
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\' => 
        array (
            0 => __DIR__ . '/..' . '/react/http/src',
        ),
        'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\' => 
        array (
            0 => __DIR__ . '/..' . '/react/event-loop/src',
        ),
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\' => 
        array (
            0 => __DIR__ . '/..' . '/react/dns/src',
        ),
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Cache\\' => 
        array (
            0 => __DIR__ . '/..' . '/react/cache/src',
        ),
        'NightwatchAgent_kden27khxA4QoEfj\\Psr\\Http\\Message\\' => 
        array (
            0 => __DIR__ . '/..' . '/psr/http-message/src',
        ),
        'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\' => 
        array (
            0 => __DIR__ . '/../..' . '/src',
        ),
        'NightwatchAgent_kden27khxA4QoEfj\\Fig\\Http\\Message\\' => 
        array (
            0 => __DIR__ . '/..' . '/fig/http-message-util/src',
        ),
        'NightwatchAgent_kden27khxA4QoEfj\\Evenement\\' => 
        array (
            0 => __DIR__ . '/..' . '/evenement/evenement/src',
        ),
    );

    public static $classMap = array (
        'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Evenement\\EventEmitter' => __DIR__ . '/..' . '/evenement/evenement/src/EventEmitter.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Evenement\\EventEmitterInterface' => __DIR__ . '/..' . '/evenement/evenement/src/EventEmitterInterface.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Evenement\\EventEmitterTrait' => __DIR__ . '/..' . '/evenement/evenement/src/EventEmitterTrait.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Fig\\Http\\Message\\RequestMethodInterface' => __DIR__ . '/..' . '/fig/http-message-util/src/RequestMethodInterface.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Fig\\Http\\Message\\StatusCodeInterface' => __DIR__ . '/..' . '/fig/http-message-util/src/StatusCodeInterface.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\Browser' => __DIR__ . '/../..' . '/src/Browser.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\CheckSignature' => __DIR__ . '/../..' . '/src/CheckSignature.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\Clock' => __DIR__ . '/../..' . '/src/Clock.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\Contracts\\Browser' => __DIR__ . '/../..' . '/src/Contracts/Browser.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\Contracts\\Clock' => __DIR__ . '/../..' . '/src/Contracts/Clock.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\Factories\\BrowserFactory' => __DIR__ . '/../..' . '/src/Factories/BrowserFactory.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\Ingest' => __DIR__ . '/../..' . '/src/Ingest.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\IngestDetails' => __DIR__ . '/../..' . '/src/IngestDetails.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\IngestDetailsRepository' => __DIR__ . '/../..' . '/src/IngestDetailsRepository.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\Loop' => __DIR__ . '/../..' . '/src/Loop.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\NullBuffer' => __DIR__ . '/../..' . '/src/NullBuffer.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\OutputWriter' => __DIR__ . '/../..' . '/src/OutputWriter.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\Payload' => __DIR__ . '/../..' . '/src/Payload.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\Server' => __DIR__ . '/../..' . '/src/Server.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Laravel\\NightwatchAgent\\StreamBuffer' => __DIR__ . '/../..' . '/src/StreamBuffer.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Psr\\Http\\Message\\MessageInterface' => __DIR__ . '/..' . '/psr/http-message/src/MessageInterface.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Psr\\Http\\Message\\RequestInterface' => __DIR__ . '/..' . '/psr/http-message/src/RequestInterface.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Psr\\Http\\Message\\ResponseInterface' => __DIR__ . '/..' . '/psr/http-message/src/ResponseInterface.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Psr\\Http\\Message\\ServerRequestInterface' => __DIR__ . '/..' . '/psr/http-message/src/ServerRequestInterface.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Psr\\Http\\Message\\StreamInterface' => __DIR__ . '/..' . '/psr/http-message/src/StreamInterface.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Psr\\Http\\Message\\UploadedFileInterface' => __DIR__ . '/..' . '/psr/http-message/src/UploadedFileInterface.php',
        'NightwatchAgent_kden27khxA4QoEfj\\Psr\\Http\\Message\\UriInterface' => __DIR__ . '/..' . '/psr/http-message/src/UriInterface.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Cache\\ArrayCache' => __DIR__ . '/..' . '/react/cache/src/ArrayCache.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Cache\\CacheInterface' => __DIR__ . '/..' . '/react/cache/src/CacheInterface.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\BadServerException' => __DIR__ . '/..' . '/react/dns/src/BadServerException.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Config\\Config' => __DIR__ . '/..' . '/react/dns/src/Config/Config.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Config\\HostsFile' => __DIR__ . '/..' . '/react/dns/src/Config/HostsFile.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Model\\Message' => __DIR__ . '/..' . '/react/dns/src/Model/Message.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Model\\Record' => __DIR__ . '/..' . '/react/dns/src/Model/Record.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Protocol\\BinaryDumper' => __DIR__ . '/..' . '/react/dns/src/Protocol/BinaryDumper.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Protocol\\Parser' => __DIR__ . '/..' . '/react/dns/src/Protocol/Parser.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\CachingExecutor' => __DIR__ . '/..' . '/react/dns/src/Query/CachingExecutor.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\CancellationException' => __DIR__ . '/..' . '/react/dns/src/Query/CancellationException.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\CoopExecutor' => __DIR__ . '/..' . '/react/dns/src/Query/CoopExecutor.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\ExecutorInterface' => __DIR__ . '/..' . '/react/dns/src/Query/ExecutorInterface.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\FallbackExecutor' => __DIR__ . '/..' . '/react/dns/src/Query/FallbackExecutor.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\HostsFileExecutor' => __DIR__ . '/..' . '/react/dns/src/Query/HostsFileExecutor.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\Query' => __DIR__ . '/..' . '/react/dns/src/Query/Query.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\RetryExecutor' => __DIR__ . '/..' . '/react/dns/src/Query/RetryExecutor.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\SelectiveTransportExecutor' => __DIR__ . '/..' . '/react/dns/src/Query/SelectiveTransportExecutor.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\TcpTransportExecutor' => __DIR__ . '/..' . '/react/dns/src/Query/TcpTransportExecutor.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\TimeoutException' => __DIR__ . '/..' . '/react/dns/src/Query/TimeoutException.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\TimeoutExecutor' => __DIR__ . '/..' . '/react/dns/src/Query/TimeoutExecutor.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Query\\UdpTransportExecutor' => __DIR__ . '/..' . '/react/dns/src/Query/UdpTransportExecutor.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\RecordNotFoundException' => __DIR__ . '/..' . '/react/dns/src/RecordNotFoundException.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Resolver\\Factory' => __DIR__ . '/..' . '/react/dns/src/Resolver/Factory.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Resolver\\Resolver' => __DIR__ . '/..' . '/react/dns/src/Resolver/Resolver.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Dns\\Resolver\\ResolverInterface' => __DIR__ . '/..' . '/react/dns/src/Resolver/ResolverInterface.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\ExtEvLoop' => __DIR__ . '/..' . '/react/event-loop/src/ExtEvLoop.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\ExtEventLoop' => __DIR__ . '/..' . '/react/event-loop/src/ExtEventLoop.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\ExtLibevLoop' => __DIR__ . '/..' . '/react/event-loop/src/ExtLibevLoop.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\ExtLibeventLoop' => __DIR__ . '/..' . '/react/event-loop/src/ExtLibeventLoop.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\ExtUvLoop' => __DIR__ . '/..' . '/react/event-loop/src/ExtUvLoop.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\Factory' => __DIR__ . '/..' . '/react/event-loop/src/Factory.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\Loop' => __DIR__ . '/..' . '/react/event-loop/src/Loop.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\LoopInterface' => __DIR__ . '/..' . '/react/event-loop/src/LoopInterface.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\SignalsHandler' => __DIR__ . '/..' . '/react/event-loop/src/SignalsHandler.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\StreamSelectLoop' => __DIR__ . '/..' . '/react/event-loop/src/StreamSelectLoop.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\Tick\\FutureTickQueue' => __DIR__ . '/..' . '/react/event-loop/src/Tick/FutureTickQueue.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\TimerInterface' => __DIR__ . '/..' . '/react/event-loop/src/TimerInterface.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\Timer\\Timer' => __DIR__ . '/..' . '/react/event-loop/src/Timer/Timer.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\EventLoop\\Timer\\Timers' => __DIR__ . '/..' . '/react/event-loop/src/Timer/Timers.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Browser' => __DIR__ . '/..' . '/react/http/src/Browser.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Client\\Client' => __DIR__ . '/..' . '/react/http/src/Client/Client.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\HttpServer' => __DIR__ . '/..' . '/react/http/src/HttpServer.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\AbstractMessage' => __DIR__ . '/..' . '/react/http/src/Io/AbstractMessage.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\AbstractRequest' => __DIR__ . '/..' . '/react/http/src/Io/AbstractRequest.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\BufferedBody' => __DIR__ . '/..' . '/react/http/src/Io/BufferedBody.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\ChunkedDecoder' => __DIR__ . '/..' . '/react/http/src/Io/ChunkedDecoder.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\ChunkedEncoder' => __DIR__ . '/..' . '/react/http/src/Io/ChunkedEncoder.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\ClientConnectionManager' => __DIR__ . '/..' . '/react/http/src/Io/ClientConnectionManager.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\ClientRequestState' => __DIR__ . '/..' . '/react/http/src/Io/ClientRequestState.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\ClientRequestStream' => __DIR__ . '/..' . '/react/http/src/Io/ClientRequestStream.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\Clock' => __DIR__ . '/..' . '/react/http/src/Io/Clock.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\CloseProtectionStream' => __DIR__ . '/..' . '/react/http/src/Io/CloseProtectionStream.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\EmptyBodyStream' => __DIR__ . '/..' . '/react/http/src/Io/EmptyBodyStream.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\HttpBodyStream' => __DIR__ . '/..' . '/react/http/src/Io/HttpBodyStream.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\IniUtil' => __DIR__ . '/..' . '/react/http/src/Io/IniUtil.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\LengthLimitedStream' => __DIR__ . '/..' . '/react/http/src/Io/LengthLimitedStream.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\MiddlewareRunner' => __DIR__ . '/..' . '/react/http/src/Io/MiddlewareRunner.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\MultipartParser' => __DIR__ . '/..' . '/react/http/src/Io/MultipartParser.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\PauseBufferStream' => __DIR__ . '/..' . '/react/http/src/Io/PauseBufferStream.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\ReadableBodyStream' => __DIR__ . '/..' . '/react/http/src/Io/ReadableBodyStream.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\RequestHeaderParser' => __DIR__ . '/..' . '/react/http/src/Io/RequestHeaderParser.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\Sender' => __DIR__ . '/..' . '/react/http/src/Io/Sender.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\StreamingServer' => __DIR__ . '/..' . '/react/http/src/Io/StreamingServer.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\Transaction' => __DIR__ . '/..' . '/react/http/src/Io/Transaction.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Io\\UploadedFile' => __DIR__ . '/..' . '/react/http/src/Io/UploadedFile.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Message\\Request' => __DIR__ . '/..' . '/react/http/src/Message/Request.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Message\\Response' => __DIR__ . '/..' . '/react/http/src/Message/Response.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Message\\ResponseException' => __DIR__ . '/..' . '/react/http/src/Message/ResponseException.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Message\\ServerRequest' => __DIR__ . '/..' . '/react/http/src/Message/ServerRequest.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Message\\Uri' => __DIR__ . '/..' . '/react/http/src/Message/Uri.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Middleware\\LimitConcurrentRequestsMiddleware' => __DIR__ . '/..' . '/react/http/src/Middleware/LimitConcurrentRequestsMiddleware.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Middleware\\RequestBodyBufferMiddleware' => __DIR__ . '/..' . '/react/http/src/Middleware/RequestBodyBufferMiddleware.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Middleware\\RequestBodyParserMiddleware' => __DIR__ . '/..' . '/react/http/src/Middleware/RequestBodyParserMiddleware.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Middleware\\StreamingRequestMiddleware' => __DIR__ . '/..' . '/react/http/src/Middleware/StreamingRequestMiddleware.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Http\\Server' => __DIR__ . '/..' . '/react/http/src/Server.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Promise\\Deferred' => __DIR__ . '/..' . '/react/promise/src/Deferred.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Promise\\Exception\\CompositeException' => __DIR__ . '/..' . '/react/promise/src/Exception/CompositeException.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Promise\\Exception\\LengthException' => __DIR__ . '/..' . '/react/promise/src/Exception/LengthException.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Promise\\Internal\\CancellationQueue' => __DIR__ . '/..' . '/react/promise/src/Internal/CancellationQueue.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Promise\\Internal\\FulfilledPromise' => __DIR__ . '/..' . '/react/promise/src/Internal/FulfilledPromise.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Promise\\Internal\\RejectedPromise' => __DIR__ . '/..' . '/react/promise/src/Internal/RejectedPromise.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Promise\\Promise' => __DIR__ . '/..' . '/react/promise/src/Promise.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Promise\\PromiseInterface' => __DIR__ . '/..' . '/react/promise/src/PromiseInterface.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\Connection' => __DIR__ . '/..' . '/react/socket/src/Connection.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\ConnectionInterface' => __DIR__ . '/..' . '/react/socket/src/ConnectionInterface.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\Connector' => __DIR__ . '/..' . '/react/socket/src/Connector.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\ConnectorInterface' => __DIR__ . '/..' . '/react/socket/src/ConnectorInterface.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\DnsConnector' => __DIR__ . '/..' . '/react/socket/src/DnsConnector.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\FdServer' => __DIR__ . '/..' . '/react/socket/src/FdServer.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\FixedUriConnector' => __DIR__ . '/..' . '/react/socket/src/FixedUriConnector.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\HappyEyeBallsConnectionBuilder' => __DIR__ . '/..' . '/react/socket/src/HappyEyeBallsConnectionBuilder.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\HappyEyeBallsConnector' => __DIR__ . '/..' . '/react/socket/src/HappyEyeBallsConnector.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\LimitingServer' => __DIR__ . '/..' . '/react/socket/src/LimitingServer.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\SecureConnector' => __DIR__ . '/..' . '/react/socket/src/SecureConnector.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\SecureServer' => __DIR__ . '/..' . '/react/socket/src/SecureServer.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\Server' => __DIR__ . '/..' . '/react/socket/src/Server.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\ServerInterface' => __DIR__ . '/..' . '/react/socket/src/ServerInterface.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\SocketServer' => __DIR__ . '/..' . '/react/socket/src/SocketServer.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\StreamEncryption' => __DIR__ . '/..' . '/react/socket/src/StreamEncryption.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\TcpConnector' => __DIR__ . '/..' . '/react/socket/src/TcpConnector.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\TcpServer' => __DIR__ . '/..' . '/react/socket/src/TcpServer.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\TimeoutConnector' => __DIR__ . '/..' . '/react/socket/src/TimeoutConnector.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\UnixConnector' => __DIR__ . '/..' . '/react/socket/src/UnixConnector.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Socket\\UnixServer' => __DIR__ . '/..' . '/react/socket/src/UnixServer.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Stream\\CompositeStream' => __DIR__ . '/..' . '/react/stream/src/CompositeStream.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Stream\\DuplexResourceStream' => __DIR__ . '/..' . '/react/stream/src/DuplexResourceStream.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Stream\\DuplexStreamInterface' => __DIR__ . '/..' . '/react/stream/src/DuplexStreamInterface.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Stream\\ReadableResourceStream' => __DIR__ . '/..' . '/react/stream/src/ReadableResourceStream.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Stream\\ReadableStreamInterface' => __DIR__ . '/..' . '/react/stream/src/ReadableStreamInterface.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Stream\\ThroughStream' => __DIR__ . '/..' . '/react/stream/src/ThroughStream.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Stream\\Util' => __DIR__ . '/..' . '/react/stream/src/Util.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Stream\\WritableResourceStream' => __DIR__ . '/..' . '/react/stream/src/WritableResourceStream.php',
        'NightwatchAgent_kden27khxA4QoEfj\\React\\Stream\\WritableStreamInterface' => __DIR__ . '/..' . '/react/stream/src/WritableStreamInterface.php',
    );

    public static function getInitializer(ClassLoader $loader)
    {
        return \Closure::bind(function () use ($loader) {
            $loader->prefixLengthsPsr4 = ComposerStaticInitzUjV6thn8dELeOw6::$prefixLengthsPsr4;
            $loader->prefixDirsPsr4 = ComposerStaticInitzUjV6thn8dELeOw6::$prefixDirsPsr4;
            $loader->classMap = ComposerStaticInitzUjV6thn8dELeOw6::$classMap;

        }, null, ClassLoader::class);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj;

return array('root' => array('name' => 'laravel/nightwatch-agent', 'pretty_version' => '0.0.0', 'version' => '0.0.0.0', 'reference' => null, 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => \false), 'versions' => array('evenement/evenement' => array('pretty_version' => 'v3.0.2', 'version' => '3.0.2.0', 'reference' => '0a16b0d71ab13284339abb99d9d2bd813640efbc', 'type' => 'library', 'install_path' => __DIR__ . '/../evenement/evenement', 'aliases' => array(), 'dev_requirement' => \false), 'fig/http-message-util' => array('pretty_version' => '1.1.5', 'version' => '1.1.5.0', 'reference' => '9d94dc0154230ac39e5bf89398b324a86f63f765', 'type' => 'library', 'install_path' => __DIR__ . '/../fig/http-message-util', 'aliases' => array(), 'dev_requirement' => \false), 'laravel/nightwatch-agent' => array('pretty_version' => '0.0.0', 'version' => '0.0.0.0', 'reference' => null, 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => \false), 'psr/http-message' => array('pretty_version' => '1.1', 'version' => '1.1.0.0', 'reference' => 'cb6ce4845ce34a8ad9e68117c10ee90a29919eba', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/http-message', 'aliases' => array(), 'dev_requirement' => \false), 'react/cache' => array('pretty_version' => 'v1.2.0', 'version' => '1.2.0.0', 'reference' => 'd47c472b64aa5608225f47965a484b75c7817d5b', 'type' => 'library', 'install_path' => __DIR__ . '/../react/cache', 'aliases' => array(), 'dev_requirement' => \false), 'react/dns' => array('pretty_version' => 'v1.14.0', 'version' => '1.14.0.0', 'reference' => '7562c05391f42701c1fccf189c8225fece1cd7c3', 'type' => 'library', 'install_path' => __DIR__ . '/../react/dns', 'aliases' => array(), 'dev_requirement' => \false), 'react/event-loop' => array('pretty_version' => 'v1.6.0', 'version' => '1.6.0.0', 'reference' => 'ba276bda6083df7e0050fd9b33f66ad7a4ac747a', 'type' => 'library', 'install_path' => __DIR__ . '/../react/event-loop', 'aliases' => array(), 'dev_requirement' => \false), 'react/http' => array('pretty_version' => 'v1.11.0', 'version' => '1.11.0.0', 'reference' => '8db02de41dcca82037367f67a2d4be365b1c4db9', 'type' => 'library', 'install_path' => __DIR__ . '/../react/http', 'aliases' => array(), 'dev_requirement' => \false), 'react/promise' => array('pretty_version' => 'v3.3.0', 'version' => '3.3.0.0', 'reference' => '23444f53a813a3296c1368bb104793ce8d88f04a', 'type' => 'library', 'install_path' => __DIR__ . '/../react/promise', 'aliases' => array(), 'dev_requirement' => \false), 'react/socket' => array('pretty_version' => 'v1.17.0', 'version' => '1.17.0.0', 'reference' => 'ef5b17b81f6f60504c539313f94f2d826c5faa08', 'type' => 'library', 'install_path' => __DIR__ . '/../react/socket', 'aliases' => array(), 'dev_requirement' => \false), 'react/stream' => array('pretty_version' => 'v1.4.0', 'version' => '1.4.0.0', 'reference' => '1e5b0acb8fe55143b5b426817155190eb6f5b18d', 'type' => 'library', 'install_path' => __DIR__ . '/../react/stream', 'aliases' => array(), 'dev_requirement' => \false)));
<?php

// platform_check.php @generated by Composer

$issues = array();

if (!(PHP_VERSION_ID >= 80200)) {
    $issues[] = 'Your Composer dependencies require a PHP version ">= 8.2.0". You are running ' . PHP_VERSION . '.';
}

if ($issues) {
    if (!headers_sent()) {
        header('HTTP/1.1 500 Internal Server Error');
    }
    if (!ini_get('display_errors')) {
        if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
            fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
        } elseif (!headers_sent()) {
            echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
        }
    }
    throw new \RuntimeException(
        'Composer detected issues in your platform: ' . implode(' ', $issues)
    );
}
Copyright (c) 2011 Igor Wiedler

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

declare (strict_types=1);
/*
 * This file is part of Evenement.
 *
 * (c) Igor Wiedler <igor@wiedler.ch>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace NightwatchAgent_kden27khxA4QoEfj\Evenement;

class EventEmitter implements EventEmitterInterface
{
    use EventEmitterTrait;
}
<?php

declare (strict_types=1);
/*
 * This file is part of Evenement.
 *
 * (c) Igor Wiedler <igor@wiedler.ch>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace NightwatchAgent_kden27khxA4QoEfj\Evenement;

interface EventEmitterInterface
{
    public function on($event, callable $listener);
    public function once($event, callable $listener);
    public function removeListener($event, callable $listener);
    public function removeAllListeners($event = null);
    public function listeners($event = null);
    public function emit($event, array $arguments = []);
}
<?php

declare (strict_types=1);
/*
 * This file is part of Evenement.
 *
 * (c) Igor Wiedler <igor@wiedler.ch>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace NightwatchAgent_kden27khxA4QoEfj\Evenement;

use InvalidArgumentException;
use function count;
use function array_keys;
use function array_merge;
use function array_search;
use function array_unique;
use function array_values;
trait EventEmitterTrait
{
    protected $listeners = [];
    protected $onceListeners = [];
    public function on($event, callable $listener)
    {
        if ($event === null) {
            throw new InvalidArgumentException('event name must not be null');
        }
        if (!isset($this->listeners[$event])) {
            $this->listeners[$event] = [];
        }
        $this->listeners[$event][] = $listener;
        return $this;
    }
    public function once($event, callable $listener)
    {
        if ($event === null) {
            throw new InvalidArgumentException('event name must not be null');
        }
        if (!isset($this->onceListeners[$event])) {
            $this->onceListeners[$event] = [];
        }
        $this->onceListeners[$event][] = $listener;
        return $this;
    }
    public function removeListener($event, callable $listener)
    {
        if ($event === null) {
            throw new InvalidArgumentException('event name must not be null');
        }
        if (isset($this->listeners[$event])) {
            $index = array_search($listener, $this->listeners[$event], \true);
            if (\false !== $index) {
                unset($this->listeners[$event][$index]);
                if (count($this->listeners[$event]) === 0) {
                    unset($this->listeners[$event]);
                }
            }
        }
        if (isset($this->onceListeners[$event])) {
            $index = array_search($listener, $this->onceListeners[$event], \true);
            if (\false !== $index) {
                unset($this->onceListeners[$event][$index]);
                if (count($this->onceListeners[$event]) === 0) {
                    unset($this->onceListeners[$event]);
                }
            }
        }
    }
    public function removeAllListeners($event = null)
    {
        if ($event !== null) {
            unset($this->listeners[$event]);
        } else {
            $this->listeners = [];
        }
        if ($event !== null) {
            unset($this->onceListeners[$event]);
        } else {
            $this->onceListeners = [];
        }
    }
    public function listeners($event = null): array
    {
        if ($event === null) {
            $events = [];
            $eventNames = array_unique(array_merge(array_keys($this->listeners), array_keys($this->onceListeners)));
            foreach ($eventNames as $eventName) {
                $events[$eventName] = array_merge(isset($this->listeners[$eventName]) ? $this->listeners[$eventName] : [], isset($this->onceListeners[$eventName]) ? $this->onceListeners[$eventName] : []);
            }
            return $events;
        }
        return array_merge(isset($this->listeners[$event]) ? $this->listeners[$event] : [], isset($this->onceListeners[$event]) ? $this->onceListeners[$event] : []);
    }
    public function emit($event, array $arguments = [])
    {
        if ($event === null) {
            throw new InvalidArgumentException('event name must not be null');
        }
        $listeners = [];
        if (isset($this->listeners[$event])) {
            $listeners = array_values($this->listeners[$event]);
        }
        $onceListeners = [];
        if (isset($this->onceListeners[$event])) {
            $onceListeners = array_values($this->onceListeners[$event]);
        }
        if (empty($listeners) === \false) {
            foreach ($listeners as $listener) {
                $listener(...$arguments);
            }
        }
        if (empty($onceListeners) === \false) {
            unset($this->onceListeners[$event]);
            foreach ($onceListeners as $listener) {
                $listener(...$arguments);
            }
        }
    }
}
Copyright (c) 2016 PHP Framework Interoperability Group

Permission is hereby granted, free of charge, to any person obtaining a copy 
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights 
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
copies of the Software, and to permit persons to whom the Software is 
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in 
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\Fig\Http\Message;

/**
 * Defines constants for common HTTP request methods.
 *
 * Usage:
 *
 * <code>
 * class RequestFactory implements RequestMethodInterface
 * {
 *     public static function factory(
 *         $uri = '/',
 *         $method = self::METHOD_GET,
 *         $data = []
 *     ) {
 *     }
 * }
 * </code>
 */
interface RequestMethodInterface
{
    const METHOD_HEAD = 'HEAD';
    const METHOD_GET = 'GET';
    const METHOD_POST = 'POST';
    const METHOD_PUT = 'PUT';
    const METHOD_PATCH = 'PATCH';
    const METHOD_DELETE = 'DELETE';
    const METHOD_PURGE = 'PURGE';
    const METHOD_OPTIONS = 'OPTIONS';
    const METHOD_TRACE = 'TRACE';
    const METHOD_CONNECT = 'CONNECT';
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\Fig\Http\Message;

/**
 * Defines constants for common HTTP status code.
 *
 * @see https://tools.ietf.org/html/rfc2295#section-8.1
 * @see https://tools.ietf.org/html/rfc2324#section-2.3
 * @see https://tools.ietf.org/html/rfc2518#section-9.7
 * @see https://tools.ietf.org/html/rfc2774#section-7
 * @see https://tools.ietf.org/html/rfc3229#section-10.4
 * @see https://tools.ietf.org/html/rfc4918#section-11
 * @see https://tools.ietf.org/html/rfc5842#section-7.1
 * @see https://tools.ietf.org/html/rfc5842#section-7.2
 * @see https://tools.ietf.org/html/rfc6585#section-3
 * @see https://tools.ietf.org/html/rfc6585#section-4
 * @see https://tools.ietf.org/html/rfc6585#section-5
 * @see https://tools.ietf.org/html/rfc6585#section-6
 * @see https://tools.ietf.org/html/rfc7231#section-6
 * @see https://tools.ietf.org/html/rfc7238#section-3
 * @see https://tools.ietf.org/html/rfc7725#section-3
 * @see https://tools.ietf.org/html/rfc7540#section-9.1.2
 * @see https://tools.ietf.org/html/rfc8297#section-2
 * @see https://tools.ietf.org/html/rfc8470#section-7
 * Usage:
 *
 * <code>
 * class ResponseFactory implements StatusCodeInterface
 * {
 *     public function createResponse($code = self::STATUS_OK)
 *     {
 *     }
 * }
 * </code>
 */
interface StatusCodeInterface
{
    // Informational 1xx
    const STATUS_CONTINUE = 100;
    const STATUS_SWITCHING_PROTOCOLS = 101;
    const STATUS_PROCESSING = 102;
    const STATUS_EARLY_HINTS = 103;
    // Successful 2xx
    const STATUS_OK = 200;
    const STATUS_CREATED = 201;
    const STATUS_ACCEPTED = 202;
    const STATUS_NON_AUTHORITATIVE_INFORMATION = 203;
    const STATUS_NO_CONTENT = 204;
    const STATUS_RESET_CONTENT = 205;
    const STATUS_PARTIAL_CONTENT = 206;
    const STATUS_MULTI_STATUS = 207;
    const STATUS_ALREADY_REPORTED = 208;
    const STATUS_IM_USED = 226;
    // Redirection 3xx
    const STATUS_MULTIPLE_CHOICES = 300;
    const STATUS_MOVED_PERMANENTLY = 301;
    const STATUS_FOUND = 302;
    const STATUS_SEE_OTHER = 303;
    const STATUS_NOT_MODIFIED = 304;
    const STATUS_USE_PROXY = 305;
    const STATUS_RESERVED = 306;
    const STATUS_TEMPORARY_REDIRECT = 307;
    const STATUS_PERMANENT_REDIRECT = 308;
    // Client Errors 4xx
    const STATUS_BAD_REQUEST = 400;
    const STATUS_UNAUTHORIZED = 401;
    const STATUS_PAYMENT_REQUIRED = 402;
    const STATUS_FORBIDDEN = 403;
    const STATUS_NOT_FOUND = 404;
    const STATUS_METHOD_NOT_ALLOWED = 405;
    const STATUS_NOT_ACCEPTABLE = 406;
    const STATUS_PROXY_AUTHENTICATION_REQUIRED = 407;
    const STATUS_REQUEST_TIMEOUT = 408;
    const STATUS_CONFLICT = 409;
    const STATUS_GONE = 410;
    const STATUS_LENGTH_REQUIRED = 411;
    const STATUS_PRECONDITION_FAILED = 412;
    const STATUS_PAYLOAD_TOO_LARGE = 413;
    const STATUS_URI_TOO_LONG = 414;
    const STATUS_UNSUPPORTED_MEDIA_TYPE = 415;
    const STATUS_RANGE_NOT_SATISFIABLE = 416;
    const STATUS_EXPECTATION_FAILED = 417;
    const STATUS_IM_A_TEAPOT = 418;
    const STATUS_MISDIRECTED_REQUEST = 421;
    const STATUS_UNPROCESSABLE_ENTITY = 422;
    const STATUS_LOCKED = 423;
    const STATUS_FAILED_DEPENDENCY = 424;
    const STATUS_TOO_EARLY = 425;
    const STATUS_UPGRADE_REQUIRED = 426;
    const STATUS_PRECONDITION_REQUIRED = 428;
    const STATUS_TOO_MANY_REQUESTS = 429;
    const STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE = 431;
    const STATUS_UNAVAILABLE_FOR_LEGAL_REASONS = 451;
    // Server Errors 5xx
    const STATUS_INTERNAL_SERVER_ERROR = 500;
    const STATUS_NOT_IMPLEMENTED = 501;
    const STATUS_BAD_GATEWAY = 502;
    const STATUS_SERVICE_UNAVAILABLE = 503;
    const STATUS_GATEWAY_TIMEOUT = 504;
    const STATUS_VERSION_NOT_SUPPORTED = 505;
    const STATUS_VARIANT_ALSO_NEGOTIATES = 506;
    const STATUS_INSUFFICIENT_STORAGE = 507;
    const STATUS_LOOP_DETECTED = 508;
    const STATUS_NOT_EXTENDED = 510;
    const STATUS_NETWORK_AUTHENTICATION_REQUIRED = 511;
}
Copyright (c) 2014 PHP Framework Interoperability Group

Permission is hereby granted, free of charge, to any person obtaining a copy 
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights 
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
copies of the Software, and to permit persons to whom the Software is 
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in 
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

declare (strict_types=1);
namespace NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message;

/**
 * HTTP messages consist of requests from a client to a server and responses
 * from a server to a client. This interface defines the methods common to
 * each.
 *
 * Messages are considered immutable; all methods that might change state MUST
 * be implemented such that they retain the internal state of the current
 * message and return an instance that contains the changed state.
 *
 * @link http://www.ietf.org/rfc/rfc7230.txt
 * @link http://www.ietf.org/rfc/rfc7231.txt
 */
interface MessageInterface
{
    /**
     * Retrieves the HTTP protocol version as a string.
     *
     * The string MUST contain only the HTTP version number (e.g., "1.1", "1.0").
     *
     * @return string HTTP protocol version.
     */
    public function getProtocolVersion();
    /**
     * Return an instance with the specified HTTP protocol version.
     *
     * The version string MUST contain only the HTTP version number (e.g.,
     * "1.1", "1.0").
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * new protocol version.
     *
     * @param string $version HTTP protocol version
     * @return static
     */
    public function withProtocolVersion(string $version);
    /**
     * Retrieves all message header values.
     *
     * The keys represent the header name as it will be sent over the wire, and
     * each value is an array of strings associated with the header.
     *
     *     // Represent the headers as a string
     *     foreach ($message->getHeaders() as $name => $values) {
     *         echo $name . ": " . implode(", ", $values);
     *     }
     *
     *     // Emit headers iteratively:
     *     foreach ($message->getHeaders() as $name => $values) {
     *         foreach ($values as $value) {
     *             header(sprintf('%s: %s', $name, $value), false);
     *         }
     *     }
     *
     * While header names are not case-sensitive, getHeaders() will preserve the
     * exact case in which headers were originally specified.
     *
     * @return string[][] Returns an associative array of the message's headers. Each
     *     key MUST be a header name, and each value MUST be an array of strings
     *     for that header.
     */
    public function getHeaders();
    /**
     * Checks if a header exists by the given case-insensitive name.
     *
     * @param string $name Case-insensitive header field name.
     * @return bool Returns true if any header names match the given header
     *     name using a case-insensitive string comparison. Returns false if
     *     no matching header name is found in the message.
     */
    public function hasHeader(string $name);
    /**
     * Retrieves a message header value by the given case-insensitive name.
     *
     * This method returns an array of all the header values of the given
     * case-insensitive header name.
     *
     * If the header does not appear in the message, this method MUST return an
     * empty array.
     *
     * @param string $name Case-insensitive header field name.
     * @return string[] An array of string values as provided for the given
     *    header. If the header does not appear in the message, this method MUST
     *    return an empty array.
     */
    public function getHeader(string $name);
    /**
     * Retrieves a comma-separated string of the values for a single header.
     *
     * This method returns all of the header values of the given
     * case-insensitive header name as a string concatenated together using
     * a comma.
     *
     * NOTE: Not all header values may be appropriately represented using
     * comma concatenation. For such headers, use getHeader() instead
     * and supply your own delimiter when concatenating.
     *
     * If the header does not appear in the message, this method MUST return
     * an empty string.
     *
     * @param string $name Case-insensitive header field name.
     * @return string A string of values as provided for the given header
     *    concatenated together using a comma. If the header does not appear in
     *    the message, this method MUST return an empty string.
     */
    public function getHeaderLine(string $name);
    /**
     * Return an instance with the provided value replacing the specified header.
     *
     * While header names are case-insensitive, the casing of the header will
     * be preserved by this function, and returned from getHeaders().
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * new and/or updated header and value.
     *
     * @param string $name Case-insensitive header field name.
     * @param string|string[] $value Header value(s).
     * @return static
     * @throws \InvalidArgumentException for invalid header names or values.
     */
    public function withHeader(string $name, $value);
    /**
     * Return an instance with the specified header appended with the given value.
     *
     * Existing values for the specified header will be maintained. The new
     * value(s) will be appended to the existing list. If the header did not
     * exist previously, it will be added.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * new header and/or value.
     *
     * @param string $name Case-insensitive header field name to add.
     * @param string|string[] $value Header value(s).
     * @return static
     * @throws \InvalidArgumentException for invalid header names or values.
     */
    public function withAddedHeader(string $name, $value);
    /**
     * Return an instance without the specified header.
     *
     * Header resolution MUST be done without case-sensitivity.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that removes
     * the named header.
     *
     * @param string $name Case-insensitive header field name to remove.
     * @return static
     */
    public function withoutHeader(string $name);
    /**
     * Gets the body of the message.
     *
     * @return StreamInterface Returns the body as a stream.
     */
    public function getBody();
    /**
     * Return an instance with the specified message body.
     *
     * The body MUST be a StreamInterface object.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return a new instance that has the
     * new body stream.
     *
     * @param StreamInterface $body Body.
     * @return static
     * @throws \InvalidArgumentException When the body is not valid.
     */
    public function withBody(StreamInterface $body);
}
<?php

declare (strict_types=1);
namespace NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message;

/**
 * Representation of an outgoing, client-side request.
 *
 * Per the HTTP specification, this interface includes properties for
 * each of the following:
 *
 * - Protocol version
 * - HTTP method
 * - URI
 * - Headers
 * - Message body
 *
 * During construction, implementations MUST attempt to set the Host header from
 * a provided URI if no Host header is provided.
 *
 * Requests are considered immutable; all methods that might change state MUST
 * be implemented such that they retain the internal state of the current
 * message and return an instance that contains the changed state.
 */
interface RequestInterface extends MessageInterface
{
    /**
     * Retrieves the message's request target.
     *
     * Retrieves the message's request-target either as it will appear (for
     * clients), as it appeared at request (for servers), or as it was
     * specified for the instance (see withRequestTarget()).
     *
     * In most cases, this will be the origin-form of the composed URI,
     * unless a value was provided to the concrete implementation (see
     * withRequestTarget() below).
     *
     * If no URI is available, and no request-target has been specifically
     * provided, this method MUST return the string "/".
     *
     * @return string
     */
    public function getRequestTarget();
    /**
     * Return an instance with the specific request-target.
     *
     * If the request needs a non-origin-form request-target — e.g., for
     * specifying an absolute-form, authority-form, or asterisk-form —
     * this method may be used to create an instance with the specified
     * request-target, verbatim.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * changed request target.
     *
     * @link http://tools.ietf.org/html/rfc7230#section-5.3 (for the various
     *     request-target forms allowed in request messages)
     * @param string $requestTarget
     * @return static
     */
    public function withRequestTarget(string $requestTarget);
    /**
     * Retrieves the HTTP method of the request.
     *
     * @return string Returns the request method.
     */
    public function getMethod();
    /**
     * Return an instance with the provided HTTP method.
     *
     * While HTTP method names are typically all uppercase characters, HTTP
     * method names are case-sensitive and thus implementations SHOULD NOT
     * modify the given string.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * changed request method.
     *
     * @param string $method Case-sensitive method.
     * @return static
     * @throws \InvalidArgumentException for invalid HTTP methods.
     */
    public function withMethod(string $method);
    /**
     * Retrieves the URI instance.
     *
     * This method MUST return a UriInterface instance.
     *
     * @link http://tools.ietf.org/html/rfc3986#section-4.3
     * @return UriInterface Returns a UriInterface instance
     *     representing the URI of the request.
     */
    public function getUri();
    /**
     * Returns an instance with the provided URI.
     *
     * This method MUST update the Host header of the returned request by
     * default if the URI contains a host component. If the URI does not
     * contain a host component, any pre-existing Host header MUST be carried
     * over to the returned request.
     *
     * You can opt-in to preserving the original state of the Host header by
     * setting `$preserveHost` to `true`. When `$preserveHost` is set to
     * `true`, this method interacts with the Host header in the following ways:
     *
     * - If the Host header is missing or empty, and the new URI contains
     *   a host component, this method MUST update the Host header in the returned
     *   request.
     * - If the Host header is missing or empty, and the new URI does not contain a
     *   host component, this method MUST NOT update the Host header in the returned
     *   request.
     * - If a Host header is present and non-empty, this method MUST NOT update
     *   the Host header in the returned request.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * new UriInterface instance.
     *
     * @link http://tools.ietf.org/html/rfc3986#section-4.3
     * @param UriInterface $uri New request URI to use.
     * @param bool $preserveHost Preserve the original state of the Host header.
     * @return static
     */
    public function withUri(UriInterface $uri, bool $preserveHost = \false);
}
<?php

declare (strict_types=1);
namespace NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message;

/**
 * Representation of an outgoing, server-side response.
 *
 * Per the HTTP specification, this interface includes properties for
 * each of the following:
 *
 * - Protocol version
 * - Status code and reason phrase
 * - Headers
 * - Message body
 *
 * Responses are considered immutable; all methods that might change state MUST
 * be implemented such that they retain the internal state of the current
 * message and return an instance that contains the changed state.
 */
interface ResponseInterface extends MessageInterface
{
    /**
     * Gets the response status code.
     *
     * The status code is a 3-digit integer result code of the server's attempt
     * to understand and satisfy the request.
     *
     * @return int Status code.
     */
    public function getStatusCode();
    /**
     * Return an instance with the specified status code and, optionally, reason phrase.
     *
     * If no reason phrase is specified, implementations MAY choose to default
     * to the RFC 7231 or IANA recommended reason phrase for the response's
     * status code.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * updated status and reason phrase.
     *
     * @link http://tools.ietf.org/html/rfc7231#section-6
     * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
     * @param int $code The 3-digit integer result code to set.
     * @param string $reasonPhrase The reason phrase to use with the
     *     provided status code; if none is provided, implementations MAY
     *     use the defaults as suggested in the HTTP specification.
     * @return static
     * @throws \InvalidArgumentException For invalid status code arguments.
     */
    public function withStatus(int $code, string $reasonPhrase = '');
    /**
     * Gets the response reason phrase associated with the status code.
     *
     * Because a reason phrase is not a required element in a response
     * status line, the reason phrase value MAY be null. Implementations MAY
     * choose to return the default RFC 7231 recommended reason phrase (or those
     * listed in the IANA HTTP Status Code Registry) for the response's
     * status code.
     *
     * @link http://tools.ietf.org/html/rfc7231#section-6
     * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
     * @return string Reason phrase; must return an empty string if none present.
     */
    public function getReasonPhrase();
}
<?php

declare (strict_types=1);
namespace NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message;

/**
 * Representation of an incoming, server-side HTTP request.
 *
 * Per the HTTP specification, this interface includes properties for
 * each of the following:
 *
 * - Protocol version
 * - HTTP method
 * - URI
 * - Headers
 * - Message body
 *
 * Additionally, it encapsulates all data as it has arrived to the
 * application from the CGI and/or PHP environment, including:
 *
 * - The values represented in $_SERVER.
 * - Any cookies provided (generally via $_COOKIE)
 * - Query string arguments (generally via $_GET, or as parsed via parse_str())
 * - Upload files, if any (as represented by $_FILES)
 * - Deserialized body parameters (generally from $_POST)
 *
 * $_SERVER values MUST be treated as immutable, as they represent application
 * state at the time of request; as such, no methods are provided to allow
 * modification of those values. The other values provide such methods, as they
 * can be restored from $_SERVER or the request body, and may need treatment
 * during the application (e.g., body parameters may be deserialized based on
 * content type).
 *
 * Additionally, this interface recognizes the utility of introspecting a
 * request to derive and match additional parameters (e.g., via URI path
 * matching, decrypting cookie values, deserializing non-form-encoded body
 * content, matching authorization headers to users, etc). These parameters
 * are stored in an "attributes" property.
 *
 * Requests are considered immutable; all methods that might change state MUST
 * be implemented such that they retain the internal state of the current
 * message and return an instance that contains the changed state.
 */
interface ServerRequestInterface extends RequestInterface
{
    /**
     * Retrieve server parameters.
     *
     * Retrieves data related to the incoming request environment,
     * typically derived from PHP's $_SERVER superglobal. The data IS NOT
     * REQUIRED to originate from $_SERVER.
     *
     * @return array
     */
    public function getServerParams();
    /**
     * Retrieve cookies.
     *
     * Retrieves cookies sent by the client to the server.
     *
     * The data MUST be compatible with the structure of the $_COOKIE
     * superglobal.
     *
     * @return array
     */
    public function getCookieParams();
    /**
     * Return an instance with the specified cookies.
     *
     * The data IS NOT REQUIRED to come from the $_COOKIE superglobal, but MUST
     * be compatible with the structure of $_COOKIE. Typically, this data will
     * be injected at instantiation.
     *
     * This method MUST NOT update the related Cookie header of the request
     * instance, nor related values in the server params.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * updated cookie values.
     *
     * @param array $cookies Array of key/value pairs representing cookies.
     * @return static
     */
    public function withCookieParams(array $cookies);
    /**
     * Retrieve query string arguments.
     *
     * Retrieves the deserialized query string arguments, if any.
     *
     * Note: the query params might not be in sync with the URI or server
     * params. If you need to ensure you are only getting the original
     * values, you may need to parse the query string from `getUri()->getQuery()`
     * or from the `QUERY_STRING` server param.
     *
     * @return array
     */
    public function getQueryParams();
    /**
     * Return an instance with the specified query string arguments.
     *
     * These values SHOULD remain immutable over the course of the incoming
     * request. They MAY be injected during instantiation, such as from PHP's
     * $_GET superglobal, or MAY be derived from some other value such as the
     * URI. In cases where the arguments are parsed from the URI, the data
     * MUST be compatible with what PHP's parse_str() would return for
     * purposes of how duplicate query parameters are handled, and how nested
     * sets are handled.
     *
     * Setting query string arguments MUST NOT change the URI stored by the
     * request, nor the values in the server params.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * updated query string arguments.
     *
     * @param array $query Array of query string arguments, typically from
     *     $_GET.
     * @return static
     */
    public function withQueryParams(array $query);
    /**
     * Retrieve normalized file upload data.
     *
     * This method returns upload metadata in a normalized tree, with each leaf
     * an instance of Psr\Http\Message\UploadedFileInterface.
     *
     * These values MAY be prepared from $_FILES or the message body during
     * instantiation, or MAY be injected via withUploadedFiles().
     *
     * @return array An array tree of UploadedFileInterface instances; an empty
     *     array MUST be returned if no data is present.
     */
    public function getUploadedFiles();
    /**
     * Create a new instance with the specified uploaded files.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * updated body parameters.
     *
     * @param array $uploadedFiles An array tree of UploadedFileInterface instances.
     * @return static
     * @throws \InvalidArgumentException if an invalid structure is provided.
     */
    public function withUploadedFiles(array $uploadedFiles);
    /**
     * Retrieve any parameters provided in the request body.
     *
     * If the request Content-Type is either application/x-www-form-urlencoded
     * or multipart/form-data, and the request method is POST, this method MUST
     * return the contents of $_POST.
     *
     * Otherwise, this method may return any results of deserializing
     * the request body content; as parsing returns structured content, the
     * potential types MUST be arrays or objects only. A null value indicates
     * the absence of body content.
     *
     * @return null|array|object The deserialized body parameters, if any.
     *     These will typically be an array or object.
     */
    public function getParsedBody();
    /**
     * Return an instance with the specified body parameters.
     *
     * These MAY be injected during instantiation.
     *
     * If the request Content-Type is either application/x-www-form-urlencoded
     * or multipart/form-data, and the request method is POST, use this method
     * ONLY to inject the contents of $_POST.
     *
     * The data IS NOT REQUIRED to come from $_POST, but MUST be the results of
     * deserializing the request body content. Deserialization/parsing returns
     * structured data, and, as such, this method ONLY accepts arrays or objects,
     * or a null value if nothing was available to parse.
     *
     * As an example, if content negotiation determines that the request data
     * is a JSON payload, this method could be used to create a request
     * instance with the deserialized parameters.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * updated body parameters.
     *
     * @param null|array|object $data The deserialized body data. This will
     *     typically be in an array or object.
     * @return static
     * @throws \InvalidArgumentException if an unsupported argument type is
     *     provided.
     */
    public function withParsedBody($data);
    /**
     * Retrieve attributes derived from the request.
     *
     * The request "attributes" may be used to allow injection of any
     * parameters derived from the request: e.g., the results of path
     * match operations; the results of decrypting cookies; the results of
     * deserializing non-form-encoded message bodies; etc. Attributes
     * will be application and request specific, and CAN be mutable.
     *
     * @return array Attributes derived from the request.
     */
    public function getAttributes();
    /**
     * Retrieve a single derived request attribute.
     *
     * Retrieves a single derived request attribute as described in
     * getAttributes(). If the attribute has not been previously set, returns
     * the default value as provided.
     *
     * This method obviates the need for a hasAttribute() method, as it allows
     * specifying a default value to return if the attribute is not found.
     *
     * @see getAttributes()
     * @param string $name The attribute name.
     * @param mixed $default Default value to return if the attribute does not exist.
     * @return mixed
     */
    public function getAttribute(string $name, $default = null);
    /**
     * Return an instance with the specified derived request attribute.
     *
     * This method allows setting a single derived request attribute as
     * described in getAttributes().
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * updated attribute.
     *
     * @see getAttributes()
     * @param string $name The attribute name.
     * @param mixed $value The value of the attribute.
     * @return static
     */
    public function withAttribute(string $name, $value);
    /**
     * Return an instance that removes the specified derived request attribute.
     *
     * This method allows removing a single derived request attribute as
     * described in getAttributes().
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that removes
     * the attribute.
     *
     * @see getAttributes()
     * @param string $name The attribute name.
     * @return static
     */
    public function withoutAttribute(string $name);
}
<?php

declare (strict_types=1);
namespace NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message;

/**
 * Describes a data stream.
 *
 * Typically, an instance will wrap a PHP stream; this interface provides
 * a wrapper around the most common operations, including serialization of
 * the entire stream to a string.
 */
interface StreamInterface
{
    /**
     * Reads all data from the stream into a string, from the beginning to end.
     *
     * This method MUST attempt to seek to the beginning of the stream before
     * reading data and read the stream until the end is reached.
     *
     * Warning: This could attempt to load a large amount of data into memory.
     *
     * This method MUST NOT raise an exception in order to conform with PHP's
     * string casting operations.
     *
     * @see http://php.net/manual/en/language.oop5.magic.php#object.tostring
     * @return string
     */
    public function __toString();
    /**
     * Closes the stream and any underlying resources.
     *
     * @return void
     */
    public function close();
    /**
     * Separates any underlying resources from the stream.
     *
     * After the stream has been detached, the stream is in an unusable state.
     *
     * @return resource|null Underlying PHP stream, if any
     */
    public function detach();
    /**
     * Get the size of the stream if known.
     *
     * @return int|null Returns the size in bytes if known, or null if unknown.
     */
    public function getSize();
    /**
     * Returns the current position of the file read/write pointer
     *
     * @return int Position of the file pointer
     * @throws \RuntimeException on error.
     */
    public function tell();
    /**
     * Returns true if the stream is at the end of the stream.
     *
     * @return bool
     */
    public function eof();
    /**
     * Returns whether or not the stream is seekable.
     *
     * @return bool
     */
    public function isSeekable();
    /**
     * Seek to a position in the stream.
     *
     * @link http://www.php.net/manual/en/function.fseek.php
     * @param int $offset Stream offset
     * @param int $whence Specifies how the cursor position will be calculated
     *     based on the seek offset. Valid values are identical to the built-in
     *     PHP $whence values for `fseek()`.  SEEK_SET: Set position equal to
     *     offset bytes SEEK_CUR: Set position to current location plus offset
     *     SEEK_END: Set position to end-of-stream plus offset.
     * @throws \RuntimeException on failure.
     */
    public function seek(int $offset, int $whence = \SEEK_SET);
    /**
     * Seek to the beginning of the stream.
     *
     * If the stream is not seekable, this method will raise an exception;
     * otherwise, it will perform a seek(0).
     *
     * @see seek()
     * @link http://www.php.net/manual/en/function.fseek.php
     * @throws \RuntimeException on failure.
     */
    public function rewind();
    /**
     * Returns whether or not the stream is writable.
     *
     * @return bool
     */
    public function isWritable();
    /**
     * Write data to the stream.
     *
     * @param string $string The string that is to be written.
     * @return int Returns the number of bytes written to the stream.
     * @throws \RuntimeException on failure.
     */
    public function write(string $string);
    /**
     * Returns whether or not the stream is readable.
     *
     * @return bool
     */
    public function isReadable();
    /**
     * Read data from the stream.
     *
     * @param int $length Read up to $length bytes from the object and return
     *     them. Fewer than $length bytes may be returned if underlying stream
     *     call returns fewer bytes.
     * @return string Returns the data read from the stream, or an empty string
     *     if no bytes are available.
     * @throws \RuntimeException if an error occurs.
     */
    public function read(int $length);
    /**
     * Returns the remaining contents in a string
     *
     * @return string
     * @throws \RuntimeException if unable to read or an error occurs while
     *     reading.
     */
    public function getContents();
    /**
     * Get stream metadata as an associative array or retrieve a specific key.
     *
     * The keys returned are identical to the keys returned from PHP's
     * stream_get_meta_data() function.
     *
     * @link http://php.net/manual/en/function.stream-get-meta-data.php
     * @param string|null $key Specific metadata to retrieve.
     * @return array|mixed|null Returns an associative array if no key is
     *     provided. Returns a specific key value if a key is provided and the
     *     value is found, or null if the key is not found.
     */
    public function getMetadata(?string $key = null);
}
<?php

declare (strict_types=1);
namespace NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message;

/**
 * Value object representing a file uploaded through an HTTP request.
 *
 * Instances of this interface are considered immutable; all methods that
 * might change state MUST be implemented such that they retain the internal
 * state of the current instance and return an instance that contains the
 * changed state.
 */
interface UploadedFileInterface
{
    /**
     * Retrieve a stream representing the uploaded file.
     *
     * This method MUST return a StreamInterface instance, representing the
     * uploaded file. The purpose of this method is to allow utilizing native PHP
     * stream functionality to manipulate the file upload, such as
     * stream_copy_to_stream() (though the result will need to be decorated in a
     * native PHP stream wrapper to work with such functions).
     *
     * If the moveTo() method has been called previously, this method MUST raise
     * an exception.
     *
     * @return StreamInterface Stream representation of the uploaded file.
     * @throws \RuntimeException in cases when no stream is available or can be
     *     created.
     */
    public function getStream();
    /**
     * Move the uploaded file to a new location.
     *
     * Use this method as an alternative to move_uploaded_file(). This method is
     * guaranteed to work in both SAPI and non-SAPI environments.
     * Implementations must determine which environment they are in, and use the
     * appropriate method (move_uploaded_file(), rename(), or a stream
     * operation) to perform the operation.
     *
     * $targetPath may be an absolute path, or a relative path. If it is a
     * relative path, resolution should be the same as used by PHP's rename()
     * function.
     *
     * The original file or stream MUST be removed on completion.
     *
     * If this method is called more than once, any subsequent calls MUST raise
     * an exception.
     *
     * When used in an SAPI environment where $_FILES is populated, when writing
     * files via moveTo(), is_uploaded_file() and move_uploaded_file() SHOULD be
     * used to ensure permissions and upload status are verified correctly.
     *
     * If you wish to move to a stream, use getStream(), as SAPI operations
     * cannot guarantee writing to stream destinations.
     *
     * @see http://php.net/is_uploaded_file
     * @see http://php.net/move_uploaded_file
     * @param string $targetPath Path to which to move the uploaded file.
     * @throws \InvalidArgumentException if the $targetPath specified is invalid.
     * @throws \RuntimeException on any error during the move operation, or on
     *     the second or subsequent call to the method.
     */
    public function moveTo(string $targetPath);
    /**
     * Retrieve the file size.
     *
     * Implementations SHOULD return the value stored in the "size" key of
     * the file in the $_FILES array if available, as PHP calculates this based
     * on the actual size transmitted.
     *
     * @return int|null The file size in bytes or null if unknown.
     */
    public function getSize();
    /**
     * Retrieve the error associated with the uploaded file.
     *
     * The return value MUST be one of PHP's UPLOAD_ERR_XXX constants.
     *
     * If the file was uploaded successfully, this method MUST return
     * UPLOAD_ERR_OK.
     *
     * Implementations SHOULD return the value stored in the "error" key of
     * the file in the $_FILES array.
     *
     * @see http://php.net/manual/en/features.file-upload.errors.php
     * @return int One of PHP's UPLOAD_ERR_XXX constants.
     */
    public function getError();
    /**
     * Retrieve the filename sent by the client.
     *
     * Do not trust the value returned by this method. A client could send
     * a malicious filename with the intention to corrupt or hack your
     * application.
     *
     * Implementations SHOULD return the value stored in the "name" key of
     * the file in the $_FILES array.
     *
     * @return string|null The filename sent by the client or null if none
     *     was provided.
     */
    public function getClientFilename();
    /**
     * Retrieve the media type sent by the client.
     *
     * Do not trust the value returned by this method. A client could send
     * a malicious media type with the intention to corrupt or hack your
     * application.
     *
     * Implementations SHOULD return the value stored in the "type" key of
     * the file in the $_FILES array.
     *
     * @return string|null The media type sent by the client or null if none
     *     was provided.
     */
    public function getClientMediaType();
}
<?php

declare (strict_types=1);
namespace NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message;

/**
 * Value object representing a URI.
 *
 * This interface is meant to represent URIs according to RFC 3986 and to
 * provide methods for most common operations. Additional functionality for
 * working with URIs can be provided on top of the interface or externally.
 * Its primary use is for HTTP requests, but may also be used in other
 * contexts.
 *
 * Instances of this interface are considered immutable; all methods that
 * might change state MUST be implemented such that they retain the internal
 * state of the current instance and return an instance that contains the
 * changed state.
 *
 * Typically the Host header will be also be present in the request message.
 * For server-side requests, the scheme will typically be discoverable in the
 * server parameters.
 *
 * @link http://tools.ietf.org/html/rfc3986 (the URI specification)
 */
interface UriInterface
{
    /**
     * Retrieve the scheme component of the URI.
     *
     * If no scheme is present, this method MUST return an empty string.
     *
     * The value returned MUST be normalized to lowercase, per RFC 3986
     * Section 3.1.
     *
     * The trailing ":" character is not part of the scheme and MUST NOT be
     * added.
     *
     * @see https://tools.ietf.org/html/rfc3986#section-3.1
     * @return string The URI scheme.
     */
    public function getScheme();
    /**
     * Retrieve the authority component of the URI.
     *
     * If no authority information is present, this method MUST return an empty
     * string.
     *
     * The authority syntax of the URI is:
     *
     * <pre>
     * [user-info@]host[:port]
     * </pre>
     *
     * If the port component is not set or is the standard port for the current
     * scheme, it SHOULD NOT be included.
     *
     * @see https://tools.ietf.org/html/rfc3986#section-3.2
     * @return string The URI authority, in "[user-info@]host[:port]" format.
     */
    public function getAuthority();
    /**
     * Retrieve the user information component of the URI.
     *
     * If no user information is present, this method MUST return an empty
     * string.
     *
     * If a user is present in the URI, this will return that value;
     * additionally, if the password is also present, it will be appended to the
     * user value, with a colon (":") separating the values.
     *
     * The trailing "@" character is not part of the user information and MUST
     * NOT be added.
     *
     * @return string The URI user information, in "username[:password]" format.
     */
    public function getUserInfo();
    /**
     * Retrieve the host component of the URI.
     *
     * If no host is present, this method MUST return an empty string.
     *
     * The value returned MUST be normalized to lowercase, per RFC 3986
     * Section 3.2.2.
     *
     * @see http://tools.ietf.org/html/rfc3986#section-3.2.2
     * @return string The URI host.
     */
    public function getHost();
    /**
     * Retrieve the port component of the URI.
     *
     * If a port is present, and it is non-standard for the current scheme,
     * this method MUST return it as an integer. If the port is the standard port
     * used with the current scheme, this method SHOULD return null.
     *
     * If no port is present, and no scheme is present, this method MUST return
     * a null value.
     *
     * If no port is present, but a scheme is present, this method MAY return
     * the standard port for that scheme, but SHOULD return null.
     *
     * @return null|int The URI port.
     */
    public function getPort();
    /**
     * Retrieve the path component of the URI.
     *
     * The path can either be empty or absolute (starting with a slash) or
     * rootless (not starting with a slash). Implementations MUST support all
     * three syntaxes.
     *
     * Normally, the empty path "" and absolute path "/" are considered equal as
     * defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically
     * do this normalization because in contexts with a trimmed base path, e.g.
     * the front controller, this difference becomes significant. It's the task
     * of the user to handle both "" and "/".
     *
     * The value returned MUST be percent-encoded, but MUST NOT double-encode
     * any characters. To determine what characters to encode, please refer to
     * RFC 3986, Sections 2 and 3.3.
     *
     * As an example, if the value should include a slash ("/") not intended as
     * delimiter between path segments, that value MUST be passed in encoded
     * form (e.g., "%2F") to the instance.
     *
     * @see https://tools.ietf.org/html/rfc3986#section-2
     * @see https://tools.ietf.org/html/rfc3986#section-3.3
     * @return string The URI path.
     */
    public function getPath();
    /**
     * Retrieve the query string of the URI.
     *
     * If no query string is present, this method MUST return an empty string.
     *
     * The leading "?" character is not part of the query and MUST NOT be
     * added.
     *
     * The value returned MUST be percent-encoded, but MUST NOT double-encode
     * any characters. To determine what characters to encode, please refer to
     * RFC 3986, Sections 2 and 3.4.
     *
     * As an example, if a value in a key/value pair of the query string should
     * include an ampersand ("&") not intended as a delimiter between values,
     * that value MUST be passed in encoded form (e.g., "%26") to the instance.
     *
     * @see https://tools.ietf.org/html/rfc3986#section-2
     * @see https://tools.ietf.org/html/rfc3986#section-3.4
     * @return string The URI query string.
     */
    public function getQuery();
    /**
     * Retrieve the fragment component of the URI.
     *
     * If no fragment is present, this method MUST return an empty string.
     *
     * The leading "#" character is not part of the fragment and MUST NOT be
     * added.
     *
     * The value returned MUST be percent-encoded, but MUST NOT double-encode
     * any characters. To determine what characters to encode, please refer to
     * RFC 3986, Sections 2 and 3.5.
     *
     * @see https://tools.ietf.org/html/rfc3986#section-2
     * @see https://tools.ietf.org/html/rfc3986#section-3.5
     * @return string The URI fragment.
     */
    public function getFragment();
    /**
     * Return an instance with the specified scheme.
     *
     * This method MUST retain the state of the current instance, and return
     * an instance that contains the specified scheme.
     *
     * Implementations MUST support the schemes "http" and "https" case
     * insensitively, and MAY accommodate other schemes if required.
     *
     * An empty scheme is equivalent to removing the scheme.
     *
     * @param string $scheme The scheme to use with the new instance.
     * @return static A new instance with the specified scheme.
     * @throws \InvalidArgumentException for invalid or unsupported schemes.
     */
    public function withScheme(string $scheme);
    /**
     * Return an instance with the specified user information.
     *
     * This method MUST retain the state of the current instance, and return
     * an instance that contains the specified user information.
     *
     * Password is optional, but the user information MUST include the
     * user; an empty string for the user is equivalent to removing user
     * information.
     *
     * @param string $user The user name to use for authority.
     * @param null|string $password The password associated with $user.
     * @return static A new instance with the specified user information.
     */
    public function withUserInfo(string $user, ?string $password = null);
    /**
     * Return an instance with the specified host.
     *
     * This method MUST retain the state of the current instance, and return
     * an instance that contains the specified host.
     *
     * An empty host value is equivalent to removing the host.
     *
     * @param string $host The hostname to use with the new instance.
     * @return static A new instance with the specified host.
     * @throws \InvalidArgumentException for invalid hostnames.
     */
    public function withHost(string $host);
    /**
     * Return an instance with the specified port.
     *
     * This method MUST retain the state of the current instance, and return
     * an instance that contains the specified port.
     *
     * Implementations MUST raise an exception for ports outside the
     * established TCP and UDP port ranges.
     *
     * A null value provided for the port is equivalent to removing the port
     * information.
     *
     * @param null|int $port The port to use with the new instance; a null value
     *     removes the port information.
     * @return static A new instance with the specified port.
     * @throws \InvalidArgumentException for invalid ports.
     */
    public function withPort(?int $port);
    /**
     * Return an instance with the specified path.
     *
     * This method MUST retain the state of the current instance, and return
     * an instance that contains the specified path.
     *
     * The path can either be empty or absolute (starting with a slash) or
     * rootless (not starting with a slash). Implementations MUST support all
     * three syntaxes.
     *
     * If the path is intended to be domain-relative rather than path relative then
     * it must begin with a slash ("/"). Paths not starting with a slash ("/")
     * are assumed to be relative to some base path known to the application or
     * consumer.
     *
     * Users can provide both encoded and decoded path characters.
     * Implementations ensure the correct encoding as outlined in getPath().
     *
     * @param string $path The path to use with the new instance.
     * @return static A new instance with the specified path.
     * @throws \InvalidArgumentException for invalid paths.
     */
    public function withPath(string $path);
    /**
     * Return an instance with the specified query string.
     *
     * This method MUST retain the state of the current instance, and return
     * an instance that contains the specified query string.
     *
     * Users can provide both encoded and decoded query characters.
     * Implementations ensure the correct encoding as outlined in getQuery().
     *
     * An empty query string value is equivalent to removing the query string.
     *
     * @param string $query The query string to use with the new instance.
     * @return static A new instance with the specified query string.
     * @throws \InvalidArgumentException for invalid query strings.
     */
    public function withQuery(string $query);
    /**
     * Return an instance with the specified URI fragment.
     *
     * This method MUST retain the state of the current instance, and return
     * an instance that contains the specified URI fragment.
     *
     * Users can provide both encoded and decoded fragment characters.
     * Implementations ensure the correct encoding as outlined in getFragment().
     *
     * An empty fragment value is equivalent to removing the fragment.
     *
     * @param string $fragment The fragment to use with the new instance.
     * @return static A new instance with the specified fragment.
     */
    public function withFragment(string $fragment);
    /**
     * Return the string representation as a URI reference.
     *
     * Depending on which components of the URI are present, the resulting
     * string is either a full URI or relative reference according to RFC 3986,
     * Section 4.1. The method concatenates the various components of the URI,
     * using the appropriate delimiters:
     *
     * - If a scheme is present, it MUST be suffixed by ":".
     * - If an authority is present, it MUST be prefixed by "//".
     * - The path can be concatenated without delimiters. But there are two
     *   cases where the path has to be adjusted to make the URI reference
     *   valid as PHP does not allow to throw an exception in __toString():
     *     - If the path is rootless and an authority is present, the path MUST
     *       be prefixed by "/".
     *     - If the path is starting with more than one "/" and no authority is
     *       present, the starting slashes MUST be reduced to one.
     * - If a query is present, it MUST be prefixed by "?".
     * - If a fragment is present, it MUST be prefixed by "#".
     *
     * @see http://tools.ietf.org/html/rfc3986#section-4.1
     * @return string
     */
    public function __toString();
}
The MIT License (MIT)

Copyright (c) 2012 Christian Lück, Cees-Jan Kiewiet, Jan Sorgalla, Chris Boden, Igor Wiedler

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Cache;

use NightwatchAgent_kden27khxA4QoEfj\React\Promise;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\PromiseInterface;
class ArrayCache implements CacheInterface
{
    private $limit;
    private $data = array();
    private $expires = array();
    private $supportsHighResolution;
    /**
     * The `ArrayCache` provides an in-memory implementation of the [`CacheInterface`](#cacheinterface).
     *
     * ```php
     * $cache = new ArrayCache();
     *
     * $cache->set('foo', 'bar');
     * ```
     *
     * Its constructor accepts an optional `?int $limit` parameter to limit the
     * maximum number of entries to store in the LRU cache. If you add more
     * entries to this instance, it will automatically take care of removing
     * the one that was least recently used (LRU).
     *
     * For example, this snippet will overwrite the first value and only store
     * the last two entries:
     *
     * ```php
     * $cache = new ArrayCache(2);
     *
     * $cache->set('foo', '1');
     * $cache->set('bar', '2');
     * $cache->set('baz', '3');
     * ```
     *
     * This cache implementation is known to rely on wall-clock time to schedule
     * future cache expiration times when using any version before PHP 7.3,
     * because a monotonic time source is only available as of PHP 7.3 (`hrtime()`).
     * While this does not affect many common use cases, this is an important
     * distinction for programs that rely on a high time precision or on systems
     * that are subject to discontinuous time adjustments (time jumps).
     * This means that if you store a cache item with a TTL of 30s on PHP < 7.3
     * and then adjust your system time forward by 20s, the cache item may
     * expire in 10s. See also [`set()`](#set) for more details.
     *
     * @param int|null $limit maximum number of entries to store in the LRU cache
     */
    public function __construct($limit = null)
    {
        $this->limit = $limit;
        // prefer high-resolution timer, available as of PHP 7.3+
        $this->supportsHighResolution = \function_exists('hrtime');
    }
    public function get($key, $default = null)
    {
        // delete key if it is already expired => below will detect this as a cache miss
        if (isset($this->expires[$key]) && $this->now() - $this->expires[$key] > 0) {
            unset($this->data[$key], $this->expires[$key]);
        }
        if (!\array_key_exists($key, $this->data)) {
            return Promise\resolve($default);
        }
        // remove and append to end of array to keep track of LRU info
        $value = $this->data[$key];
        unset($this->data[$key]);
        $this->data[$key] = $value;
        return Promise\resolve($value);
    }
    public function set($key, $value, $ttl = null)
    {
        // unset before setting to ensure this entry will be added to end of array (LRU info)
        unset($this->data[$key]);
        $this->data[$key] = $value;
        // sort expiration times if TTL is given (first will expire first)
        unset($this->expires[$key]);
        if ($ttl !== null) {
            $this->expires[$key] = $this->now() + $ttl;
            \asort($this->expires);
        }
        // ensure size limit is not exceeded or remove first entry from array
        if ($this->limit !== null && \count($this->data) > $this->limit) {
            // first try to check if there's any expired entry
            // expiration times are sorted, so we can simply look at the first one
            \reset($this->expires);
            $key = \key($this->expires);
            // check to see if the first in the list of expiring keys is already expired
            // if the first key is not expired, we have to overwrite by using LRU info
            if ($key === null || $this->now() - $this->expires[$key] < 0) {
                \reset($this->data);
                $key = \key($this->data);
            }
            unset($this->data[$key], $this->expires[$key]);
        }
        return Promise\resolve(\true);
    }
    public function delete($key)
    {
        unset($this->data[$key], $this->expires[$key]);
        return Promise\resolve(\true);
    }
    public function getMultiple(array $keys, $default = null)
    {
        $values = array();
        foreach ($keys as $key) {
            $values[$key] = $this->get($key, $default);
        }
        return Promise\all($values);
    }
    public function setMultiple(array $values, $ttl = null)
    {
        foreach ($values as $key => $value) {
            $this->set($key, $value, $ttl);
        }
        return Promise\resolve(\true);
    }
    public function deleteMultiple(array $keys)
    {
        foreach ($keys as $key) {
            unset($this->data[$key], $this->expires[$key]);
        }
        return Promise\resolve(\true);
    }
    public function clear()
    {
        $this->data = array();
        $this->expires = array();
        return Promise\resolve(\true);
    }
    public function has($key)
    {
        // delete key if it is already expired
        if (isset($this->expires[$key]) && $this->now() - $this->expires[$key] > 0) {
            unset($this->data[$key], $this->expires[$key]);
        }
        if (!\array_key_exists($key, $this->data)) {
            return Promise\resolve(\false);
        }
        // remove and append to end of array to keep track of LRU info
        $value = $this->data[$key];
        unset($this->data[$key]);
        $this->data[$key] = $value;
        return Promise\resolve(\true);
    }
    /**
     * @return float
     */
    private function now()
    {
        return $this->supportsHighResolution ? \hrtime(\true) * 1.0E-9 : \microtime(\true);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Cache;

use NightwatchAgent_kden27khxA4QoEfj\React\Promise\PromiseInterface;
interface CacheInterface
{
    /**
     * Retrieves an item from the cache.
     *
     * This method will resolve with the cached value on success or with the
     * given `$default` value when no item can be found or when an error occurs.
     * Similarly, an expired cache item (once the time-to-live is expired) is
     * considered a cache miss.
     *
     * ```php
     * $cache
     *     ->get('foo')
     *     ->then('var_dump');
     * ```
     *
     * This example fetches the value of the key `foo` and passes it to the
     * `var_dump` function. You can use any of the composition provided by
     * [promises](https://github.com/reactphp/promise).
     *
     * @param string $key
     * @param mixed  $default Default value to return for cache miss or null if not given.
     * @return PromiseInterface<mixed>
     */
    public function get($key, $default = null);
    /**
     * Stores an item in the cache.
     *
     * This method will resolve with `true` on success or `false` when an error
     * occurs. If the cache implementation has to go over the network to store
     * it, it may take a while.
     *
     * The optional `$ttl` parameter sets the maximum time-to-live in seconds
     * for this cache item. If this parameter is omitted (or `null`), the item
     * will stay in the cache for as long as the underlying implementation
     * supports. Trying to access an expired cache item results in a cache miss,
     * see also [`get()`](#get).
     *
     * ```php
     * $cache->set('foo', 'bar', 60);
     * ```
     *
     * This example eventually sets the value of the key `foo` to `bar`. If it
     * already exists, it is overridden.
     *
     * This interface does not enforce any particular TTL resolution, so special
     * care may have to be taken if you rely on very high precision with
     * millisecond accuracy or below. Cache implementations SHOULD work on a
     * best effort basis and SHOULD provide at least second accuracy unless
     * otherwise noted. Many existing cache implementations are known to provide
     * microsecond or millisecond accuracy, but it's generally not recommended
     * to rely on this high precision.
     *
     * This interface suggests that cache implementations SHOULD use a monotonic
     * time source if available. Given that a monotonic time source is only
     * available as of PHP 7.3 by default, cache implementations MAY fall back
     * to using wall-clock time.
     * While this does not affect many common use cases, this is an important
     * distinction for programs that rely on a high time precision or on systems
     * that are subject to discontinuous time adjustments (time jumps).
     * This means that if you store a cache item with a TTL of 30s and then
     * adjust your system time forward by 20s, the cache item SHOULD still
     * expire in 30s.
     *
     * @param string $key
     * @param mixed  $value
     * @param ?float $ttl
     * @return PromiseInterface<bool> Returns a promise which resolves to `true` on success or `false` on error
     */
    public function set($key, $value, $ttl = null);
    /**
     * Deletes an item from the cache.
     *
     * This method will resolve with `true` on success or `false` when an error
     * occurs. When no item for `$key` is found in the cache, it also resolves
     * to `true`. If the cache implementation has to go over the network to
     * delete it, it may take a while.
     *
     * ```php
     * $cache->delete('foo');
     * ```
     *
     * This example eventually deletes the key `foo` from the cache. As with
     * `set()`, this may not happen instantly and a promise is returned to
     * provide guarantees whether or not the item has been removed from cache.
     *
     * @param string $key
     * @return PromiseInterface<bool> Returns a promise which resolves to `true` on success or `false` on error
     */
    public function delete($key);
    /**
     * Retrieves multiple cache items by their unique keys.
     *
     * This method will resolve with an array of cached values on success or with the
     * given `$default` value when an item can not be found or when an error occurs.
     * Similarly, an expired cache item (once the time-to-live is expired) is
     * considered a cache miss.
     *
     * ```php
     * $cache->getMultiple(array('name', 'age'))->then(function (array $values) {
     *     $name = $values['name'] ?? 'User';
     *     $age = $values['age'] ?? 'n/a';
     *
     *     echo $name . ' is ' . $age . PHP_EOL;
     * });
     * ```
     *
     * This example fetches the cache items for the `name` and `age` keys and
     * prints some example output. You can use any of the composition provided
     * by [promises](https://github.com/reactphp/promise).
     *
     * @param string[] $keys A list of keys that can obtained in a single operation.
     * @param mixed $default Default value to return for keys that do not exist.
     * @return PromiseInterface<array> Returns a promise which resolves to an `array` of cached values
     */
    public function getMultiple(array $keys, $default = null);
    /**
     * Persists a set of key => value pairs in the cache, with an optional TTL.
     *
     * This method will resolve with `true` on success or `false` when an error
     * occurs. If the cache implementation has to go over the network to store
     * it, it may take a while.
     *
     * The optional `$ttl` parameter sets the maximum time-to-live in seconds
     * for these cache items. If this parameter is omitted (or `null`), these items
     * will stay in the cache for as long as the underlying implementation
     * supports. Trying to access an expired cache items results in a cache miss,
     * see also [`get()`](#get).
     *
     * ```php
     * $cache->setMultiple(array('foo' => 1, 'bar' => 2), 60);
     * ```
     *
     * This example eventually sets the list of values - the key `foo` to 1 value
     * and the key `bar` to 2. If some of the keys already exist, they are overridden.
     *
     * @param array  $values A list of key => value pairs for a multiple-set operation.
     * @param ?float $ttl    Optional. The TTL value of this item.
     * @return PromiseInterface<bool> Returns a promise which resolves to `true` on success or `false` on error
     */
    public function setMultiple(array $values, $ttl = null);
    /**
     * Deletes multiple cache items in a single operation.
     *
     * @param string[] $keys A list of string-based keys to be deleted.
     * @return PromiseInterface<bool> Returns a promise which resolves to `true` on success or `false` on error
     */
    public function deleteMultiple(array $keys);
    /**
     * Wipes clean the entire cache.
     *
     * @return PromiseInterface<bool> Returns a promise which resolves to `true` on success or `false` on error
     */
    public function clear();
    /**
     * Determines whether an item is present in the cache.
     *
     * This method will resolve with `true` on success or `false` when no item can be found
     * or when an error occurs. Similarly, an expired cache item (once the time-to-live
     * is expired) is considered a cache miss.
     *
     * ```php
     * $cache
     *     ->has('foo')
     *     ->then('var_dump');
     * ```
     *
     * This example checks if the value of the key `foo` is set in the cache and passes
     * the result to the `var_dump` function. You can use any of the composition provided by
     * [promises](https://github.com/reactphp/promise).
     *
     * NOTE: It is recommended that has() is only to be used for cache warming type purposes
     * and not to be used within your live applications operations for get/set, as this method
     * is subject to a race condition where your has() will return true and immediately after,
     * another script can remove it making the state of your app out of date.
     *
     * @param string $key The cache item key.
     * @return PromiseInterface<bool> Returns a promise which resolves to `true` on success or `false` on error
     */
    public function has($key);
}
The MIT License (MIT)

Copyright (c) 2012 Christian Lück, Cees-Jan Kiewiet, Jan Sorgalla, Chris Boden, Igor Wiedler

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns;

final class BadServerException extends \Exception
{
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns\Config;

use RuntimeException;
final class Config
{
    /**
     * Loads the system DNS configuration
     *
     * Note that this method may block while loading its internal files and/or
     * commands and should thus be used with care! While this should be
     * relatively fast for most systems, it remains unknown if this may block
     * under certain circumstances. In particular, this method should only be
     * executed before the loop starts, not while it is running.
     *
     * Note that this method will try to access its files and/or commands and
     * try to parse its output. Currently, this will only parse valid nameserver
     * entries from its output and will ignore all other output without
     * complaining.
     *
     * Note that the previous section implies that this may return an empty
     * `Config` object if no valid nameserver entries can be found.
     *
     * @return self
     * @codeCoverageIgnore
     */
    public static function loadSystemConfigBlocking()
    {
        // Use WMIC output on Windows
        if (\DIRECTORY_SEPARATOR === '\\') {
            return self::loadWmicBlocking();
        }
        // otherwise (try to) load from resolv.conf
        try {
            return self::loadResolvConfBlocking();
        } catch (RuntimeException $ignored) {
            // return empty config if parsing fails (file not found)
            return new self();
        }
    }
    /**
     * Loads a resolv.conf file (from the given path or default location)
     *
     * Note that this method blocks while loading the given path and should
     * thus be used with care! While this should be relatively fast for normal
     * resolv.conf files, this may be an issue if this file is located on a slow
     * device or contains an excessive number of entries. In particular, this
     * method should only be executed before the loop starts, not while it is
     * running.
     *
     * Note that this method will throw if the given file can not be loaded,
     * such as if it is not readable or does not exist. In particular, this file
     * is not available on Windows.
     *
     * Currently, this will only parse valid "nameserver X" lines from the
     * given file contents. Lines can be commented out with "#" and ";" and
     * invalid lines will be ignored without complaining. See also
     * `man resolv.conf` for more details.
     *
     * Note that the previous section implies that this may return an empty
     * `Config` object if no valid "nameserver X" lines can be found. See also
     * `man resolv.conf` which suggests that the DNS server on the localhost
     * should be used in this case. This is left up to higher level consumers
     * of this API.
     *
     * @param ?string $path (optional) path to resolv.conf file or null=load default location
     * @return self
     * @throws RuntimeException if the path can not be loaded (does not exist)
     */
    public static function loadResolvConfBlocking($path = null)
    {
        if ($path === null) {
            $path = '/etc/resolv.conf';
        }
        $contents = @file_get_contents($path);
        if ($contents === \false) {
            throw new RuntimeException('Unable to load resolv.conf file "' . $path . '"');
        }
        $matches = array();
        preg_match_all('/^nameserver\s+(\S+)\s*$/m', $contents, $matches);
        $config = new self();
        foreach ($matches[1] as $ip) {
            // remove IPv6 zone ID (`fe80::1%lo0` => `fe80:1`)
            if (strpos($ip, ':') !== \false && ($pos = strpos($ip, '%')) !== \false) {
                $ip = substr($ip, 0, $pos);
            }
            if (@inet_pton($ip) !== \false) {
                $config->nameservers[] = $ip;
            }
        }
        return $config;
    }
    /**
     * Loads the DNS configurations from Windows's WMIC (from the given command or default command)
     *
     * Note that this method blocks while loading the given command and should
     * thus be used with care! While this should be relatively fast for normal
     * WMIC commands, it remains unknown if this may block under certain
     * circumstances. In particular, this method should only be executed before
     * the loop starts, not while it is running.
     *
     * Note that this method will only try to execute the given command try to
     * parse its output, irrespective of whether this command exists. In
     * particular, this command is only available on Windows. Currently, this
     * will only parse valid nameserver entries from the command output and will
     * ignore all other output without complaining.
     *
     * Note that the previous section implies that this may return an empty
     * `Config` object if no valid nameserver entries can be found.
     *
     * @param ?string $command (advanced) should not be given (NULL) unless you know what you're doing
     * @return self
     * @link https://ss64.com/nt/wmic.html
     */
    public static function loadWmicBlocking($command = null)
    {
        $contents = shell_exec($command === null ? 'wmic NICCONFIG get "DNSServerSearchOrder" /format:CSV' : $command);
        preg_match_all('/(?<=[{;,"])([\da-f.:]{4,})(?=[};,"])/i', $contents, $matches);
        $config = new self();
        $config->nameservers = $matches[1];
        return $config;
    }
    public $nameservers = array();
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns\Config;

use RuntimeException;
/**
 * Represents a static hosts file which maps hostnames to IPs
 *
 * Hosts files are used on most systems to avoid actually hitting the DNS for
 * certain common hostnames.
 *
 * Most notably, this file usually contains an entry to map "localhost" to the
 * local IP. Windows is a notable exception here, as Windows does not actually
 * include "localhost" in this file by default. To compensate for this, this
 * class may explicitly be wrapped in another HostsFile instance which
 * hard-codes these entries for Windows (see also Factory).
 *
 * This class mostly exists to abstract the parsing/extraction process so this
 * can be replaced with a faster alternative in the future.
 */
class HostsFile
{
    /**
     * Returns the default path for the hosts file on this system
     *
     * @return string
     * @codeCoverageIgnore
     */
    public static function getDefaultPath()
    {
        // use static path for all Unix-based systems
        if (\DIRECTORY_SEPARATOR !== '\\') {
            return '/etc/hosts';
        }
        // Windows actually stores the path in the registry under
        // \HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\DataBasePath
        $path = '%SystemRoot%\system32\drivers\etc\hosts';
        $base = getenv('SystemRoot');
        if ($base === \false) {
            $base = 'C:\Windows';
        }
        return str_replace('%SystemRoot%', $base, $path);
    }
    /**
     * Loads a hosts file (from the given path or default location)
     *
     * Note that this method blocks while loading the given path and should
     * thus be used with care! While this should be relatively fast for normal
     * hosts file, this may be an issue if this file is located on a slow device
     * or contains an excessive number of entries. In particular, this method
     * should only be executed before the loop starts, not while it is running.
     *
     * @param ?string $path (optional) path to hosts file or null=load default location
     * @return self
     * @throws RuntimeException if the path can not be loaded (does not exist)
     */
    public static function loadFromPathBlocking($path = null)
    {
        if ($path === null) {
            $path = self::getDefaultPath();
        }
        $contents = @file_get_contents($path);
        if ($contents === \false) {
            throw new RuntimeException('Unable to load hosts file "' . $path . '"');
        }
        return new self($contents);
    }
    private $contents;
    /**
     * Instantiate new hosts file with the given hosts file contents
     *
     * @param string $contents
     */
    public function __construct($contents)
    {
        // remove all comments from the contents
        $contents = preg_replace('/[ \t]*#.*/', '', strtolower($contents));
        $this->contents = $contents;
    }
    /**
     * Returns all IPs for the given hostname
     *
     * @param string $name
     * @return string[]
     */
    public function getIpsForHost($name)
    {
        $name = strtolower($name);
        $ips = array();
        foreach (preg_split('/\r?\n/', $this->contents) as $line) {
            $parts = preg_split('/\s+/', $line);
            $ip = array_shift($parts);
            if ($parts && array_search($name, $parts) !== \false) {
                // remove IPv6 zone ID (`fe80::1%lo0` => `fe80:1`)
                if (strpos($ip, ':') !== \false && ($pos = strpos($ip, '%')) !== \false) {
                    $ip = substr($ip, 0, $pos);
                }
                if (@inet_pton($ip) !== \false) {
                    $ips[] = $ip;
                }
            }
        }
        return $ips;
    }
    /**
     * Returns all hostnames for the given IPv4 or IPv6 address
     *
     * @param string $ip
     * @return string[]
     */
    public function getHostsForIp($ip)
    {
        // check binary representation of IP to avoid string case and short notation
        $ip = @inet_pton($ip);
        if ($ip === \false) {
            return array();
        }
        $names = array();
        foreach (preg_split('/\r?\n/', $this->contents) as $line) {
            $parts = preg_split('/\s+/', $line, -1, \PREG_SPLIT_NO_EMPTY);
            $addr = (string) array_shift($parts);
            // remove IPv6 zone ID (`fe80::1%lo0` => `fe80:1`)
            if (strpos($addr, ':') !== \false && ($pos = strpos($addr, '%')) !== \false) {
                $addr = substr($addr, 0, $pos);
            }
            if (@inet_pton($addr) === $ip) {
                foreach ($parts as $part) {
                    $names[] = $part;
                }
            }
        }
        return $names;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns\Model;

use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query\Query;
/**
 * This class represents an outgoing query message or an incoming response message
 *
 * @link https://tools.ietf.org/html/rfc1035#section-4.1.1
 */
final class Message
{
    const TYPE_A = 1;
    const TYPE_NS = 2;
    const TYPE_CNAME = 5;
    const TYPE_SOA = 6;
    const TYPE_PTR = 12;
    const TYPE_MX = 15;
    const TYPE_TXT = 16;
    const TYPE_AAAA = 28;
    const TYPE_SRV = 33;
    const TYPE_SSHFP = 44;
    /**
     * pseudo-type for EDNS0
     *
     * These are included in the additional section and usually not in answer section.
     * Defined in [RFC 6891](https://tools.ietf.org/html/rfc6891) (or older
     * [RFC 2671](https://tools.ietf.org/html/rfc2671)).
     *
     * The OPT record uses the "class" field to store the maximum size.
     *
     * The OPT record uses the "ttl" field to store additional flags.
     */
    const TYPE_OPT = 41;
    /**
     * Sender Policy Framework (SPF) had a dedicated SPF type which has been
     * deprecated in favor of reusing the existing TXT type.
     *
     * @deprecated https://datatracker.ietf.org/doc/html/rfc7208#section-3.1
     * @see self::TYPE_TXT
     */
    const TYPE_SPF = 99;
    const TYPE_ANY = 255;
    const TYPE_CAA = 257;
    const CLASS_IN = 1;
    const OPCODE_QUERY = 0;
    const OPCODE_IQUERY = 1;
    // inverse query
    const OPCODE_STATUS = 2;
    const RCODE_OK = 0;
    const RCODE_FORMAT_ERROR = 1;
    const RCODE_SERVER_FAILURE = 2;
    const RCODE_NAME_ERROR = 3;
    const RCODE_NOT_IMPLEMENTED = 4;
    const RCODE_REFUSED = 5;
    /**
     * The edns-tcp-keepalive EDNS0 Option
     *
     * Option value contains a `?float` with timeout in seconds (in 0.1s steps)
     * for DNS response or `null` for DNS query.
     *
     * @link https://tools.ietf.org/html/rfc7828
     */
    const OPT_TCP_KEEPALIVE = 11;
    /**
     * The EDNS(0) Padding Option
     *
     * Option value contains a `string` with binary data (usually variable
     * number of null bytes)
     *
     * @link https://tools.ietf.org/html/rfc7830
     */
    const OPT_PADDING = 12;
    /**
     * Creates a new request message for the given query
     *
     * @param Query $query
     * @return self
     */
    public static function createRequestForQuery(Query $query)
    {
        $request = new Message();
        $request->id = self::generateId();
        $request->rd = \true;
        $request->questions[] = $query;
        return $request;
    }
    /**
     * Creates a new response message for the given query with the given answer records
     *
     * @param Query    $query
     * @param Record[] $answers
     * @return self
     */
    public static function createResponseWithAnswersForQuery(Query $query, array $answers)
    {
        $response = new Message();
        $response->id = self::generateId();
        $response->qr = \true;
        $response->rd = \true;
        $response->questions[] = $query;
        foreach ($answers as $record) {
            $response->answers[] = $record;
        }
        return $response;
    }
    /**
     * generates a random 16 bit message ID
     *
     * This uses a CSPRNG so that an outside attacker that is sending spoofed
     * DNS response messages can not guess the message ID to avoid possible
     * cache poisoning attacks.
     *
     * The `random_int()` function is only available on PHP 7+ or when
     * https://github.com/paragonie/random_compat is installed. As such, using
     * the latest supported PHP version is highly recommended. This currently
     * falls back to a less secure random number generator on older PHP versions
     * in the hope that this system is properly protected against outside
     * attackers, for example by using one of the common local DNS proxy stubs.
     *
     * @return int
     * @see self::getId()
     * @codeCoverageIgnore
     */
    private static function generateId()
    {
        if (function_exists('random_int')) {
            return random_int(0, 0xffff);
        }
        return mt_rand(0, 0xffff);
    }
    /**
     * The 16 bit message ID
     *
     * The response message ID has to match the request message ID. This allows
     * the receiver to verify this is the correct response message. An outside
     * attacker may try to inject fake responses by "guessing" the message ID,
     * so this should use a proper CSPRNG to avoid possible cache poisoning.
     *
     * @var int 16 bit message ID
     * @see self::generateId()
     */
    public $id = 0;
    /**
     * @var bool Query/Response flag, query=false or response=true
     */
    public $qr = \false;
    /**
     * @var int specifies the kind of query (4 bit), see self::OPCODE_* constants
     * @see self::OPCODE_QUERY
     */
    public $opcode = self::OPCODE_QUERY;
    /**
     *
     * @var bool Authoritative Answer
     */
    public $aa = \false;
    /**
     * @var bool TrunCation
     */
    public $tc = \false;
    /**
     * @var bool Recursion Desired
     */
    public $rd = \false;
    /**
     * @var bool Recursion Available
     */
    public $ra = \false;
    /**
     * @var int response code (4 bit), see self::RCODE_* constants
     * @see self::RCODE_OK
     */
    public $rcode = Message::RCODE_OK;
    /**
     * An array of Query objects
     *
     * ```php
     * $questions = array(
     *     new Query(
     *         'reactphp.org',
     *         Message::TYPE_A,
     *         Message::CLASS_IN
     *     )
     * );
     * ```
     *
     * @var Query[]
     */
    public $questions = array();
    /**
     * @var Record[]
     */
    public $answers = array();
    /**
     * @var Record[]
     */
    public $authority = array();
    /**
     * @var Record[]
     */
    public $additional = array();
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns\Model;

/**
 * This class represents a single resulting record in a response message
 *
 * It uses a structure similar to `\React\Dns\Query\Query`, but does include
 * fields for resulting TTL and resulting record data (IPs etc.).
 *
 * @link https://tools.ietf.org/html/rfc1035#section-4.1.3
 * @see \React\Dns\Query\Query
 */
final class Record
{
    /**
     * @var string hostname without trailing dot, for example "reactphp.org"
     */
    public $name;
    /**
     * @var int see Message::TYPE_* constants (UINT16)
     */
    public $type;
    /**
     * Defines the network class, usually `Message::CLASS_IN`.
     *
     * For `OPT` records (EDNS0), this defines the maximum message size instead.
     *
     * @var int see Message::CLASS_IN constant (UINT16)
     * @see Message::CLASS_IN
     */
    public $class;
    /**
     * Defines the maximum time-to-live (TTL) in seconds
     *
     * For `OPT` records (EDNS0), this defines additional flags instead.
     *
     * @var int maximum TTL in seconds (UINT32, most significant bit always unset)
     * @link https://tools.ietf.org/html/rfc2181#section-8
     * @link https://tools.ietf.org/html/rfc6891#section-6.1.3 for `OPT` records (EDNS0)
     */
    public $ttl;
    /**
     * The payload data for this record
     *
     * The payload data format depends on the record type. As a rule of thumb,
     * this library will try to express this in a way that can be consumed
     * easily without having to worry about DNS internals and its binary transport:
     *
     * - A:
     *   IPv4 address string, for example "192.168.1.1".
     *
     * - AAAA:
     *   IPv6 address string, for example "::1".
     *
     * - CNAME / PTR / NS:
     *   The hostname without trailing dot, for example "reactphp.org".
     *
     * - TXT:
     *   List of string values, for example `["v=spf1 include:example.com"]`.
     *   This is commonly a list with only a single string value, but this
     *   technically allows multiple strings (0-255 bytes each) in a single
     *   record. This is rarely used and depending on application you may want
     *   to join these together or handle them separately. Each string can
     *   transport any binary data, its character encoding is not defined (often
     *   ASCII/UTF-8 in practice). [RFC 1464](https://tools.ietf.org/html/rfc1464)
     *   suggests using key-value pairs such as `["name=test","version=1"]`, but
     *   interpretation of this is not enforced and left up to consumers of this
     *   library (used for DNS-SD/Zeroconf and others).
     *
     * - MX:
     *   Mail server priority (UINT16) and target hostname without trailing dot,
     *   for example `{"priority":10,"target":"mx.example.com"}`.
     *   The payload data uses an associative array with fixed keys "priority"
     *   (also commonly referred to as weight or preference) and "target" (also
     *   referred to as exchange). If a response message contains multiple
     *   records of this type, targets should be sorted by priority (lowest
     *   first) - this is left up to consumers of this library (used for SMTP).
     *
     * - SRV:
     *   Service priority (UINT16), service weight (UINT16), service port (UINT16)
     *   and target hostname without trailing dot, for example
     *   `{"priority":10,"weight":50,"port":8080,"target":"example.com"}`.
     *   The payload data uses an associative array with fixed keys "priority",
     *   "weight", "port" and "target" (also referred to as name).
     *   The target may be an empty host name string if the service is decidedly
     *   not available. If a response message contains multiple records of this
     *   type, targets should be sorted by priority (lowest first) and selected
     *   randomly according to their weight - this is left up to consumers of
     *   this library, see also [RFC 2782](https://tools.ietf.org/html/rfc2782)
     *   for more details.
     *
     * - SSHFP:
     *   Includes algorithm (UNIT8), fingerprint type (UNIT8) and fingerprint
     *   value as lower case hex string, for example:
     *   `{"algorithm":1,"type":1,"fingerprint":"0123456789abcdef..."}`
     *   See also https://www.iana.org/assignments/dns-sshfp-rr-parameters/dns-sshfp-rr-parameters.xhtml
     *   for algorithm and fingerprint type assignments.
     *
     * - SOA:
     *   Includes master hostname without trailing dot, responsible person email
     *   as hostname without trailing dot and serial, refresh, retry, expire and
     *   minimum times in seconds (UINT32 each), for example:
     *   `{"mname":"ns.example.com","rname":"hostmaster.example.com","serial":
     *   2018082601,"refresh":3600,"retry":1800,"expire":60000,"minimum":3600}`.
     *
     * - CAA:
     *   Includes flag (UNIT8), tag string and value string, for example:
     *   `{"flag":128,"tag":"issue","value":"letsencrypt.org"}`
     *
     * - OPT:
     *   Special pseudo-type for EDNS0. Includes an array of additional opt codes
     *   with a value according to the respective OPT code. See `Message::OPT_*`
     *   for list of supported OPT codes. Any other OPT code not currently
     *   supported will be an opaque binary string containing the raw data
     *   as transported in the DNS record. For forwards compatibility, you should
     *   not rely on this format for unknown types. Future versions may add
     *   support for new types and this may then parse the payload data
     *   appropriately - this will not be considered a BC break. See also
     *   [RFC 6891](https://tools.ietf.org/html/rfc6891) for more details.
     *
     * - Any other unknown type:
     *   An opaque binary string containing the RDATA as transported in the DNS
     *   record. For forwards compatibility, you should not rely on this format
     *   for unknown types. Future versions may add support for new types and
     *   this may then parse the payload data appropriately - this will not be
     *   considered a BC break. See the format definition of known types above
     *   for more details.
     *
     * @var string|string[]|array
     */
    public $data;
    /**
     * @param string                $name
     * @param int                   $type
     * @param int                   $class
     * @param int                   $ttl
     * @param string|string[]|array $data
     */
    public function __construct($name, $type, $class, $ttl, $data)
    {
        $this->name = $name;
        $this->type = $type;
        $this->class = $class;
        $this->ttl = $ttl;
        $this->data = $data;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns\Protocol;

use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Model\Message;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Model\Record;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query\Query;
final class BinaryDumper
{
    /**
     * @param Message $message
     * @return string
     */
    public function toBinary(Message $message)
    {
        $data = '';
        $data .= $this->headerToBinary($message);
        $data .= $this->questionToBinary($message->questions);
        $data .= $this->recordsToBinary($message->answers);
        $data .= $this->recordsToBinary($message->authority);
        $data .= $this->recordsToBinary($message->additional);
        return $data;
    }
    /**
     * @param Message $message
     * @return string
     */
    private function headerToBinary(Message $message)
    {
        $data = '';
        $data .= pack('n', $message->id);
        $flags = 0x0;
        $flags = $flags << 1 | ($message->qr ? 1 : 0);
        $flags = $flags << 4 | $message->opcode;
        $flags = $flags << 1 | ($message->aa ? 1 : 0);
        $flags = $flags << 1 | ($message->tc ? 1 : 0);
        $flags = $flags << 1 | ($message->rd ? 1 : 0);
        $flags = $flags << 1 | ($message->ra ? 1 : 0);
        $flags = $flags << 3 | 0;
        // skip unused zero bit
        $flags = $flags << 4 | $message->rcode;
        $data .= pack('n', $flags);
        $data .= pack('n', count($message->questions));
        $data .= pack('n', count($message->answers));
        $data .= pack('n', count($message->authority));
        $data .= pack('n', count($message->additional));
        return $data;
    }
    /**
     * @param Query[] $questions
     * @return string
     */
    private function questionToBinary(array $questions)
    {
        $data = '';
        foreach ($questions as $question) {
            $data .= $this->domainNameToBinary($question->name);
            $data .= pack('n*', $question->type, $question->class);
        }
        return $data;
    }
    /**
     * @param Record[] $records
     * @return string
     */
    private function recordsToBinary(array $records)
    {
        $data = '';
        foreach ($records as $record) {
            /* @var $record Record */
            switch ($record->type) {
                case Message::TYPE_A:
                case Message::TYPE_AAAA:
                    $binary = \inet_pton($record->data);
                    break;
                case Message::TYPE_CNAME:
                case Message::TYPE_NS:
                case Message::TYPE_PTR:
                    $binary = $this->domainNameToBinary($record->data);
                    break;
                case Message::TYPE_TXT:
                case Message::TYPE_SPF:
                    $binary = $this->textsToBinary($record->data);
                    break;
                case Message::TYPE_MX:
                    $binary = \pack('n', $record->data['priority']);
                    $binary .= $this->domainNameToBinary($record->data['target']);
                    break;
                case Message::TYPE_SRV:
                    $binary = \pack('n*', $record->data['priority'], $record->data['weight'], $record->data['port']);
                    $binary .= $this->domainNameToBinary($record->data['target']);
                    break;
                case Message::TYPE_SOA:
                    $binary = $this->domainNameToBinary($record->data['mname']);
                    $binary .= $this->domainNameToBinary($record->data['rname']);
                    $binary .= \pack('N*', $record->data['serial'], $record->data['refresh'], $record->data['retry'], $record->data['expire'], $record->data['minimum']);
                    break;
                case Message::TYPE_CAA:
                    $binary = \pack('C*', $record->data['flag'], \strlen($record->data['tag']));
                    $binary .= $record->data['tag'];
                    $binary .= $record->data['value'];
                    break;
                case Message::TYPE_SSHFP:
                    $binary = \pack('CCH*', $record->data['algorithm'], $record->data['type'], $record->data['fingerprint']);
                    break;
                case Message::TYPE_OPT:
                    $binary = '';
                    foreach ($record->data as $opt => $value) {
                        if ($opt === Message::OPT_TCP_KEEPALIVE && $value !== null) {
                            $value = \pack('n', round($value * 10));
                        }
                        $binary .= \pack('n*', $opt, \strlen((string) $value)) . $value;
                    }
                    break;
                default:
                    // RDATA is already stored as binary value for unknown record types
                    $binary = $record->data;
            }
            $data .= $this->domainNameToBinary($record->name);
            $data .= \pack('nnNn', $record->type, $record->class, $record->ttl, \strlen($binary));
            $data .= $binary;
        }
        return $data;
    }
    /**
     * @param string[] $texts
     * @return string
     */
    private function textsToBinary(array $texts)
    {
        $data = '';
        foreach ($texts as $text) {
            $data .= \chr(\strlen($text)) . $text;
        }
        return $data;
    }
    /**
     * @param string $host
     * @return string
     */
    private function domainNameToBinary($host)
    {
        if ($host === '') {
            return "\x00";
        }
        // break up domain name at each dot that is not preceeded by a backslash (escaped notation)
        return $this->textsToBinary(\array_map('stripcslashes', \preg_split('/(?<!\\\\)\./', $host . '.')));
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns\Protocol;

use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Model\Message;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Model\Record;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query\Query;
use InvalidArgumentException;
/**
 * DNS protocol parser
 *
 * Obsolete and uncommon types and classes are not implemented.
 */
final class Parser
{
    /**
     * Parses the given raw binary message into a Message object
     *
     * @param string $data
     * @throws InvalidArgumentException
     * @return Message
     */
    public function parseMessage($data)
    {
        $message = $this->parse($data, 0);
        if ($message === null) {
            throw new InvalidArgumentException('Unable to parse binary message');
        }
        return $message;
    }
    /**
     * @param string $data
     * @param int    $consumed
     * @return ?Message
     */
    private function parse($data, $consumed)
    {
        if (!isset($data[12 - 1])) {
            return null;
        }
        list($id, $fields, $qdCount, $anCount, $nsCount, $arCount) = array_values(unpack('n*', substr($data, 0, 12)));
        $message = new Message();
        $message->id = $id;
        $message->rcode = $fields & 0xf;
        $message->ra = ($fields >> 7 & 1) === 1;
        $message->rd = ($fields >> 8 & 1) === 1;
        $message->tc = ($fields >> 9 & 1) === 1;
        $message->aa = ($fields >> 10 & 1) === 1;
        $message->opcode = $fields >> 11 & 0xf;
        $message->qr = ($fields >> 15 & 1) === 1;
        $consumed += 12;
        // parse all questions
        for ($i = $qdCount; $i > 0; --$i) {
            list($question, $consumed) = $this->parseQuestion($data, $consumed);
            if ($question === null) {
                return null;
            } else {
                $message->questions[] = $question;
            }
        }
        // parse all answer records
        for ($i = $anCount; $i > 0; --$i) {
            list($record, $consumed) = $this->parseRecord($data, $consumed);
            if ($record === null) {
                return null;
            } else {
                $message->answers[] = $record;
            }
        }
        // parse all authority records
        for ($i = $nsCount; $i > 0; --$i) {
            list($record, $consumed) = $this->parseRecord($data, $consumed);
            if ($record === null) {
                return null;
            } else {
                $message->authority[] = $record;
            }
        }
        // parse all additional records
        for ($i = $arCount; $i > 0; --$i) {
            list($record, $consumed) = $this->parseRecord($data, $consumed);
            if ($record === null) {
                return null;
            } else {
                $message->additional[] = $record;
            }
        }
        return $message;
    }
    /**
     * @param string $data
     * @param int $consumed
     * @return array
     */
    private function parseQuestion($data, $consumed)
    {
        list($labels, $consumed) = $this->readLabels($data, $consumed);
        if ($labels === null || !isset($data[$consumed + 4 - 1])) {
            return array(null, null);
        }
        list($type, $class) = array_values(unpack('n*', substr($data, $consumed, 4)));
        $consumed += 4;
        return array(new Query(implode('.', $labels), $type, $class), $consumed);
    }
    /**
     * @param string $data
     * @param int $consumed
     * @return array An array with a parsed Record on success or array with null if data is invalid/incomplete
     */
    private function parseRecord($data, $consumed)
    {
        list($name, $consumed) = $this->readDomain($data, $consumed);
        if ($name === null || !isset($data[$consumed + 10 - 1])) {
            return array(null, null);
        }
        list($type, $class) = array_values(unpack('n*', substr($data, $consumed, 4)));
        $consumed += 4;
        list($ttl) = array_values(unpack('N', substr($data, $consumed, 4)));
        $consumed += 4;
        // TTL is a UINT32 that must not have most significant bit set for BC reasons
        if ($ttl < 0 || $ttl >= 1 << 31) {
            $ttl = 0;
        }
        list($rdLength) = array_values(unpack('n', substr($data, $consumed, 2)));
        $consumed += 2;
        if (!isset($data[$consumed + $rdLength - 1])) {
            return array(null, null);
        }
        $rdata = null;
        $expected = $consumed + $rdLength;
        if (Message::TYPE_A === $type) {
            if ($rdLength === 4) {
                $rdata = inet_ntop(substr($data, $consumed, $rdLength));
                $consumed += $rdLength;
            }
        } elseif (Message::TYPE_AAAA === $type) {
            if ($rdLength === 16) {
                $rdata = inet_ntop(substr($data, $consumed, $rdLength));
                $consumed += $rdLength;
            }
        } elseif (Message::TYPE_CNAME === $type || Message::TYPE_PTR === $type || Message::TYPE_NS === $type) {
            list($rdata, $consumed) = $this->readDomain($data, $consumed);
        } elseif (Message::TYPE_TXT === $type || Message::TYPE_SPF === $type) {
            $rdata = array();
            while ($consumed < $expected) {
                $len = ord($data[$consumed]);
                $rdata[] = (string) substr($data, $consumed + 1, $len);
                $consumed += $len + 1;
            }
        } elseif (Message::TYPE_MX === $type) {
            if ($rdLength > 2) {
                list($priority) = array_values(unpack('n', substr($data, $consumed, 2)));
                list($target, $consumed) = $this->readDomain($data, $consumed + 2);
                $rdata = array('priority' => $priority, 'target' => $target);
            }
        } elseif (Message::TYPE_SRV === $type) {
            if ($rdLength > 6) {
                list($priority, $weight, $port) = array_values(unpack('n*', substr($data, $consumed, 6)));
                list($target, $consumed) = $this->readDomain($data, $consumed + 6);
                $rdata = array('priority' => $priority, 'weight' => $weight, 'port' => $port, 'target' => $target);
            }
        } elseif (Message::TYPE_SSHFP === $type) {
            if ($rdLength > 2) {
                list($algorithm, $hash) = \array_values(\unpack('C*', \substr($data, $consumed, 2)));
                $fingerprint = \bin2hex(\substr($data, $consumed + 2, $rdLength - 2));
                $consumed += $rdLength;
                $rdata = array('algorithm' => $algorithm, 'type' => $hash, 'fingerprint' => $fingerprint);
            }
        } elseif (Message::TYPE_SOA === $type) {
            list($mname, $consumed) = $this->readDomain($data, $consumed);
            list($rname, $consumed) = $this->readDomain($data, $consumed);
            if ($mname !== null && $rname !== null && isset($data[$consumed + 20 - 1])) {
                list($serial, $refresh, $retry, $expire, $minimum) = array_values(unpack('N*', substr($data, $consumed, 20)));
                $consumed += 20;
                $rdata = array('mname' => $mname, 'rname' => $rname, 'serial' => $serial, 'refresh' => $refresh, 'retry' => $retry, 'expire' => $expire, 'minimum' => $minimum);
            }
        } elseif (Message::TYPE_OPT === $type) {
            $rdata = array();
            while (isset($data[$consumed + 4 - 1])) {
                list($code, $length) = array_values(unpack('n*', substr($data, $consumed, 4)));
                $value = (string) substr($data, $consumed + 4, $length);
                if ($code === Message::OPT_TCP_KEEPALIVE && $value === '') {
                    $value = null;
                } elseif ($code === Message::OPT_TCP_KEEPALIVE && $length === 2) {
                    list($value) = array_values(unpack('n', $value));
                    $value = round($value * 0.1, 1);
                } elseif ($code === Message::OPT_TCP_KEEPALIVE) {
                    break;
                }
                $rdata[$code] = $value;
                $consumed += 4 + $length;
            }
        } elseif (Message::TYPE_CAA === $type) {
            if ($rdLength > 3) {
                list($flag, $tagLength) = array_values(unpack('C*', substr($data, $consumed, 2)));
                if ($tagLength > 0 && $rdLength - 2 - $tagLength > 0) {
                    $tag = substr($data, $consumed + 2, $tagLength);
                    $value = substr($data, $consumed + 2 + $tagLength, $rdLength - 2 - $tagLength);
                    $consumed += $rdLength;
                    $rdata = array('flag' => $flag, 'tag' => $tag, 'value' => $value);
                }
            }
        } else {
            // unknown types simply parse rdata as an opaque binary string
            $rdata = substr($data, $consumed, $rdLength);
            $consumed += $rdLength;
        }
        // ensure parsing record data consumes expact number of bytes indicated in record length
        if ($consumed !== $expected || $rdata === null) {
            return array(null, null);
        }
        return array(new Record($name, $type, $class, $ttl, $rdata), $consumed);
    }
    private function readDomain($data, $consumed)
    {
        list($labels, $consumed) = $this->readLabels($data, $consumed);
        if ($labels === null) {
            return array(null, null);
        }
        // use escaped notation for each label part, then join using dots
        return array(\implode('.', \array_map(function ($label) {
            return \addcslashes($label, "\x00.. .");
        }, $labels)), $consumed);
    }
    /**
     * @param string $data
     * @param int    $consumed
     * @param int    $compressionDepth maximum depth for compressed labels to avoid unreasonable recursion
     * @return array
     */
    private function readLabels($data, $consumed, $compressionDepth = 127)
    {
        $labels = array();
        while (\true) {
            if (!isset($data[$consumed])) {
                return array(null, null);
            }
            $length = \ord($data[$consumed]);
            // end of labels reached
            if ($length === 0) {
                $consumed += 1;
                break;
            }
            // first two bits set? this is a compressed label (14 bit pointer offset)
            if (($length & 0xc0) === 0xc0 && isset($data[$consumed + 1]) && $compressionDepth) {
                $offset = ($length & ~0xc0) << 8 | \ord($data[$consumed + 1]);
                if ($offset >= $consumed) {
                    return array(null, null);
                }
                $consumed += 2;
                list($newLabels) = $this->readLabels($data, $offset, $compressionDepth - 1);
                if ($newLabels === null) {
                    return array(null, null);
                }
                $labels = array_merge($labels, $newLabels);
                break;
            }
            // length MUST be 0-63 (6 bits only) and data has to be large enough
            if ($length & 0xc0 || !isset($data[$consumed + $length - 1])) {
                return array(null, null);
            }
            $labels[] = substr($data, $consumed + 1, $length);
            $consumed += $length + 1;
        }
        return array($labels, $consumed);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query;

use NightwatchAgent_kden27khxA4QoEfj\React\Cache\CacheInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Model\Message;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\Promise;
final class CachingExecutor implements ExecutorInterface
{
    /**
     * Default TTL for negative responses (NXDOMAIN etc.).
     *
     * @internal
     */
    const TTL = 60;
    private $executor;
    private $cache;
    public function __construct(ExecutorInterface $executor, CacheInterface $cache)
    {
        $this->executor = $executor;
        $this->cache = $cache;
    }
    public function query(Query $query)
    {
        $id = $query->name . ':' . $query->type . ':' . $query->class;
        $cache = $this->cache;
        $that = $this;
        $executor = $this->executor;
        $pending = $cache->get($id);
        return new Promise(function ($resolve, $reject) use ($query, $id, $cache, $executor, &$pending, $that) {
            $pending->then(function ($message) use ($query, $id, $cache, $executor, &$pending, $that) {
                // return cached response message on cache hit
                if ($message !== null) {
                    return $message;
                }
                // perform DNS lookup if not already cached
                return $pending = $executor->query($query)->then(function (Message $message) use ($cache, $id, $that) {
                    // DNS response message received => store in cache when not truncated and return
                    if (!$message->tc) {
                        $cache->set($id, $message, $that->ttl($message));
                    }
                    return $message;
                });
            })->then($resolve, function ($e) use ($reject, &$pending) {
                $reject($e);
                $pending = null;
            });
        }, function ($_, $reject) use (&$pending, $query) {
            $reject(new \RuntimeException('DNS query for ' . $query->describe() . ' has been cancelled'));
            $pending->cancel();
            $pending = null;
        });
    }
    /**
     * @param Message $message
     * @return int
     * @internal
     */
    public function ttl(Message $message)
    {
        // select TTL from answers (should all be the same), use smallest value if available
        // @link https://tools.ietf.org/html/rfc2181#section-5.2
        $ttl = null;
        foreach ($message->answers as $answer) {
            if ($ttl === null || $answer->ttl < $ttl) {
                $ttl = $answer->ttl;
            }
        }
        if ($ttl === null) {
            $ttl = self::TTL;
        }
        return $ttl;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query;

final class CancellationException extends \RuntimeException
{
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query;

use NightwatchAgent_kden27khxA4QoEfj\React\Promise\Promise;
/**
 * Cooperatively resolves hosts via the given base executor to ensure same query is not run concurrently
 *
 * Wraps an existing `ExecutorInterface` to keep tracking of pending queries
 * and only starts a new query when the same query is not already pending. Once
 * the underlying query is fulfilled/rejected, it will forward its value to all
 * promises awaiting the same query.
 *
 * This means it will not limit concurrency for queries that differ, for example
 * when sending many queries for different host names or types.
 *
 * This is useful because all executors are entirely async and as such allow you
 * to execute any number of queries concurrently. You should probably limit the
 * number of concurrent queries in your application or you're very likely going
 * to face rate limitations and bans on the resolver end. For many common
 * applications, you may want to avoid sending the same query multiple times
 * when the first one is still pending, so you will likely want to use this in
 * combination with some other executor like this:
 *
 * ```php
 * $executor = new CoopExecutor(
 *     new RetryExecutor(
 *         new TimeoutExecutor(
 *             new UdpTransportExecutor($nameserver),
 *             3.0
 *         )
 *     )
 * );
 * ```
 */
final class CoopExecutor implements ExecutorInterface
{
    private $executor;
    private $pending = array();
    private $counts = array();
    public function __construct(ExecutorInterface $base)
    {
        $this->executor = $base;
    }
    public function query(Query $query)
    {
        $key = $this->serializeQueryToIdentity($query);
        if (isset($this->pending[$key])) {
            // same query is already pending, so use shared reference to pending query
            $promise = $this->pending[$key];
            ++$this->counts[$key];
        } else {
            // no such query pending, so start new query and keep reference until it's fulfilled or rejected
            $promise = $this->executor->query($query);
            $this->pending[$key] = $promise;
            $this->counts[$key] = 1;
            $pending =& $this->pending;
            $counts =& $this->counts;
            $promise->then(function () use ($key, &$pending, &$counts) {
                unset($pending[$key], $counts[$key]);
            }, function () use ($key, &$pending, &$counts) {
                unset($pending[$key], $counts[$key]);
            });
        }
        // Return a child promise awaiting the pending query.
        // Cancelling this child promise should only cancel the pending query
        // when no other child promise is awaiting the same query.
        $pending =& $this->pending;
        $counts =& $this->counts;
        return new Promise(function ($resolve, $reject) use ($promise) {
            $promise->then($resolve, $reject);
        }, function () use (&$promise, $key, $query, &$pending, &$counts) {
            if (--$counts[$key] < 1) {
                unset($pending[$key], $counts[$key]);
                $promise->cancel();
                $promise = null;
            }
            throw new \RuntimeException('DNS query for ' . $query->describe() . ' has been cancelled');
        });
    }
    private function serializeQueryToIdentity(Query $query)
    {
        return sprintf('%s:%s:%s', $query->name, $query->type, $query->class);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query;

interface ExecutorInterface
{
    /**
     * Executes a query and will return a response message
     *
     * It returns a Promise which either fulfills with a response
     * `React\Dns\Model\Message` on success or rejects with an `Exception` if
     * the query is not successful. A response message may indicate an error
     * condition in its `rcode`, but this is considered a valid response message.
     *
     * ```php
     * $executor->query($query)->then(
     *     function (React\Dns\Model\Message $response) {
     *         // response message successfully received
     *         var_dump($response->rcode, $response->answers);
     *     },
     *     function (Exception $error) {
     *         // failed to query due to $error
     *     }
     * );
     * ```
     *
     * The returned Promise MUST be implemented in such a way that it can be
     * cancelled when it is still pending. Cancelling a pending promise MUST
     * reject its value with an Exception. It SHOULD clean up any underlying
     * resources and references as applicable.
     *
     * ```php
     * $promise = $executor->query($query);
     *
     * $promise->cancel();
     * ```
     *
     * @param Query $query
     * @return \React\Promise\PromiseInterface<\React\Dns\Model\Message>
     *     resolves with response message on success or rejects with an Exception on error
     */
    public function query(Query $query);
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query;

use NightwatchAgent_kden27khxA4QoEfj\React\Promise\Promise;
final class FallbackExecutor implements ExecutorInterface
{
    private $executor;
    private $fallback;
    public function __construct(ExecutorInterface $executor, ExecutorInterface $fallback)
    {
        $this->executor = $executor;
        $this->fallback = $fallback;
    }
    public function query(Query $query)
    {
        $cancelled = \false;
        $fallback = $this->fallback;
        $promise = $this->executor->query($query);
        return new Promise(function ($resolve, $reject) use (&$promise, $fallback, $query, &$cancelled) {
            $promise->then($resolve, function (\Exception $e1) use ($fallback, $query, $resolve, $reject, &$cancelled, &$promise) {
                // reject if primary resolution rejected due to cancellation
                if ($cancelled) {
                    $reject($e1);
                    return;
                }
                // start fallback query if primary query rejected
                $promise = $fallback->query($query)->then($resolve, function (\Exception $e2) use ($e1, $reject) {
                    $append = $e2->getMessage();
                    if (($pos = strpos($append, ':')) !== \false) {
                        $append = substr($append, $pos + 2);
                    }
                    // reject with combined error message if both queries fail
                    $reject(new \RuntimeException($e1->getMessage() . '. ' . $append));
                });
            });
        }, function () use (&$promise, &$cancelled) {
            // cancel pending query (primary or fallback)
            $cancelled = \true;
            $promise->cancel();
        });
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query;

use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Config\HostsFile;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Model\Message;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Model\Record;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise;
/**
 * Resolves hosts from the given HostsFile or falls back to another executor
 *
 * If the host is found in the hosts file, it will not be passed to the actual
 * DNS executor. If the host is not found in the hosts file, it will be passed
 * to the DNS executor as a fallback.
 */
final class HostsFileExecutor implements ExecutorInterface
{
    private $hosts;
    private $fallback;
    public function __construct(HostsFile $hosts, ExecutorInterface $fallback)
    {
        $this->hosts = $hosts;
        $this->fallback = $fallback;
    }
    public function query(Query $query)
    {
        if ($query->class === Message::CLASS_IN && ($query->type === Message::TYPE_A || $query->type === Message::TYPE_AAAA)) {
            // forward lookup for type A or AAAA
            $records = array();
            $expectsColon = $query->type === Message::TYPE_AAAA;
            foreach ($this->hosts->getIpsForHost($query->name) as $ip) {
                // ensure this is an IPv4/IPV6 address according to query type
                if ((strpos($ip, ':') !== \false) === $expectsColon) {
                    $records[] = new Record($query->name, $query->type, $query->class, 0, $ip);
                }
            }
            if ($records) {
                return Promise\resolve(Message::createResponseWithAnswersForQuery($query, $records));
            }
        } elseif ($query->class === Message::CLASS_IN && $query->type === Message::TYPE_PTR) {
            // reverse lookup: extract IPv4 or IPv6 from special `.arpa` domain
            $ip = $this->getIpFromHost($query->name);
            if ($ip !== null) {
                $records = array();
                foreach ($this->hosts->getHostsForIp($ip) as $host) {
                    $records[] = new Record($query->name, $query->type, $query->class, 0, $host);
                }
                if ($records) {
                    return Promise\resolve(Message::createResponseWithAnswersForQuery($query, $records));
                }
            }
        }
        return $this->fallback->query($query);
    }
    private function getIpFromHost($host)
    {
        if (substr($host, -13) === '.in-addr.arpa') {
            // IPv4: read as IP and reverse bytes
            $ip = @inet_pton(substr($host, 0, -13));
            if ($ip === \false || isset($ip[4])) {
                return null;
            }
            return inet_ntop(strrev($ip));
        } elseif (substr($host, -9) === '.ip6.arpa') {
            // IPv6: replace dots, reverse nibbles and interpret as hexadecimal string
            $ip = @inet_ntop(pack('H*', strrev(str_replace('.', '', substr($host, 0, -9)))));
            if ($ip === \false) {
                return null;
            }
            return $ip;
        } else {
            return null;
        }
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query;

use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Model\Message;
/**
 * This class represents a single question in a query/response message
 *
 * It uses a structure similar to `\React\Dns\Message\Record`, but does not
 * contain fields for resulting TTL and resulting record data (IPs etc.).
 *
 * @link https://tools.ietf.org/html/rfc1035#section-4.1.2
 * @see \React\Dns\Message\Record
 */
final class Query
{
    /**
     * @var string query name, i.e. hostname to look up
     */
    public $name;
    /**
     * @var int query type (aka QTYPE), see Message::TYPE_* constants
     */
    public $type;
    /**
     * @var int query class (aka QCLASS), see Message::CLASS_IN constant
     */
    public $class;
    /**
     * @param string $name  query name, i.e. hostname to look up
     * @param int    $type  query type, see Message::TYPE_* constants
     * @param int    $class query class, see Message::CLASS_IN constant
     */
    public function __construct($name, $type, $class)
    {
        $this->name = $name;
        $this->type = $type;
        $this->class = $class;
    }
    /**
     * Describes the hostname and query type/class for this query
     *
     * The output format is supposed to be human readable and is subject to change.
     * The format is inspired by RFC 3597 when handling unkown types/classes.
     *
     * @return string "example.com (A)" or "example.com (CLASS0 TYPE1234)"
     * @link https://tools.ietf.org/html/rfc3597
     */
    public function describe()
    {
        $class = $this->class !== Message::CLASS_IN ? 'CLASS' . $this->class . ' ' : '';
        $type = 'TYPE' . $this->type;
        $ref = new \ReflectionClass('NightwatchAgent_kden27khxA4QoEfj\React\Dns\Model\Message');
        foreach ($ref->getConstants() as $name => $value) {
            if ($value === $this->type && \strpos($name, 'TYPE_') === 0) {
                $type = \substr($name, 5);
                break;
            }
        }
        return $this->name . ' (' . $class . $type . ')';
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query;

use NightwatchAgent_kden27khxA4QoEfj\React\Promise\Deferred;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\PromiseInterface;
final class RetryExecutor implements ExecutorInterface
{
    private $executor;
    private $retries;
    public function __construct(ExecutorInterface $executor, $retries = 2)
    {
        $this->executor = $executor;
        $this->retries = $retries;
    }
    public function query(Query $query)
    {
        return $this->tryQuery($query, $this->retries);
    }
    public function tryQuery(Query $query, $retries)
    {
        $deferred = new Deferred(function () use (&$promise) {
            if ($promise instanceof PromiseInterface && \method_exists($promise, 'cancel')) {
                $promise->cancel();
            }
        });
        $success = function ($value) use ($deferred, &$errorback) {
            $errorback = null;
            $deferred->resolve($value);
        };
        $executor = $this->executor;
        $errorback = function ($e) use ($deferred, &$promise, $query, $success, &$errorback, &$retries, $executor) {
            if (!$e instanceof TimeoutException) {
                $errorback = null;
                $deferred->reject($e);
            } elseif ($retries <= 0) {
                $errorback = null;
                $deferred->reject($e = new \RuntimeException('DNS query for ' . $query->describe() . ' failed: too many retries', 0, $e));
                // avoid garbage references by replacing all closures in call stack.
                // what a lovely piece of code!
                $r = new \ReflectionProperty('Exception', 'trace');
                if (\PHP_VERSION_ID < 80100) {
                    $r->setAccessible(\true);
                }
                $trace = $r->getValue($e);
                // Exception trace arguments are not available on some PHP 7.4 installs
                // @codeCoverageIgnoreStart
                foreach ($trace as $ti => $one) {
                    if (isset($one['args'])) {
                        foreach ($one['args'] as $ai => $arg) {
                            if ($arg instanceof \Closure) {
                                $trace[$ti]['args'][$ai] = 'Object(' . \get_class($arg) . ')';
                            }
                        }
                    }
                }
                // @codeCoverageIgnoreEnd
                $r->setValue($e, $trace);
            } else {
                --$retries;
                $promise = $executor->query($query)->then($success, $errorback);
            }
        };
        $promise = $this->executor->query($query)->then($success, $errorback);
        return $deferred->promise();
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query;

use NightwatchAgent_kden27khxA4QoEfj\React\Promise\Promise;
/**
 * Send DNS queries over a UDP or TCP/IP stream transport.
 *
 * This class will automatically choose the correct transport protocol to send
 * a DNS query to your DNS server. It will always try to send it over the more
 * efficient UDP transport first. If this query yields a size related issue
 * (truncated messages), it will retry over a streaming TCP/IP transport.
 *
 * For more advanced usages one can utilize this class directly.
 * The following example looks up the `IPv6` address for `reactphp.org`.
 *
 * ```php
 * $executor = new SelectiveTransportExecutor($udpExecutor, $tcpExecutor);
 *
 * $executor->query(
 *     new Query($name, Message::TYPE_AAAA, Message::CLASS_IN)
 * )->then(function (Message $message) {
 *     foreach ($message->answers as $answer) {
 *         echo 'IPv6: ' . $answer->data . PHP_EOL;
 *     }
 * }, 'printf');
 * ```
 *
 * Note that this executor only implements the logic to select the correct
 * transport for the given DNS query. Implementing the correct transport logic,
 * implementing timeouts and any retry logic is left up to the given executors,
 * see also [`UdpTransportExecutor`](#udptransportexecutor) and
 * [`TcpTransportExecutor`](#tcptransportexecutor) for more details.
 *
 * Note that this executor is entirely async and as such allows you to execute
 * any number of queries concurrently. You should probably limit the number of
 * concurrent queries in your application or you're very likely going to face
 * rate limitations and bans on the resolver end. For many common applications,
 * you may want to avoid sending the same query multiple times when the first
 * one is still pending, so you will likely want to use this in combination with
 * a `CoopExecutor` like this:
 *
 * ```php
 * $executor = new CoopExecutor(
 *     new SelectiveTransportExecutor(
 *         $datagramExecutor,
 *         $streamExecutor
 *     )
 * );
 * ```
 */
class SelectiveTransportExecutor implements ExecutorInterface
{
    private $datagramExecutor;
    private $streamExecutor;
    public function __construct(ExecutorInterface $datagramExecutor, ExecutorInterface $streamExecutor)
    {
        $this->datagramExecutor = $datagramExecutor;
        $this->streamExecutor = $streamExecutor;
    }
    public function query(Query $query)
    {
        $stream = $this->streamExecutor;
        $pending = $this->datagramExecutor->query($query);
        return new Promise(function ($resolve, $reject) use (&$pending, $stream, $query) {
            $pending->then($resolve, function ($e) use (&$pending, $stream, $query, $resolve, $reject) {
                if ($e->getCode() === (\defined('SOCKET_EMSGSIZE') ? \SOCKET_EMSGSIZE : 90)) {
                    $pending = $stream->query($query)->then($resolve, $reject);
                } else {
                    $reject($e);
                }
            });
        }, function () use (&$pending) {
            $pending->cancel();
            $pending = null;
        });
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query;

use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Model\Message;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Protocol\BinaryDumper;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Protocol\Parser;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Loop;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\Deferred;
/**
 * Send DNS queries over a TCP/IP stream transport.
 *
 * This is one of the main classes that send a DNS query to your DNS server.
 *
 * For more advanced usages one can utilize this class directly.
 * The following example looks up the `IPv6` address for `reactphp.org`.
 *
 * ```php
 * $executor = new TcpTransportExecutor('8.8.8.8:53');
 *
 * $executor->query(
 *     new Query($name, Message::TYPE_AAAA, Message::CLASS_IN)
 * )->then(function (Message $message) {
 *     foreach ($message->answers as $answer) {
 *         echo 'IPv6: ' . $answer->data . PHP_EOL;
 *     }
 * }, 'printf');
 * ```
 *
 * See also [example #92](examples).
 *
 * Note that this executor does not implement a timeout, so you will very likely
 * want to use this in combination with a `TimeoutExecutor` like this:
 *
 * ```php
 * $executor = new TimeoutExecutor(
 *     new TcpTransportExecutor($nameserver),
 *     3.0
 * );
 * ```
 *
 * Unlike the `UdpTransportExecutor`, this class uses a reliable TCP/IP
 * transport, so you do not necessarily have to implement any retry logic.
 *
 * Note that this executor is entirely async and as such allows you to execute
 * queries concurrently. The first query will establish a TCP/IP socket
 * connection to the DNS server which will be kept open for a short period.
 * Additional queries will automatically reuse this existing socket connection
 * to the DNS server, will pipeline multiple requests over this single
 * connection and will keep an idle connection open for a short period. The
 * initial TCP/IP connection overhead may incur a slight delay if you only send
 * occasional queries – when sending a larger number of concurrent queries over
 * an existing connection, it becomes increasingly more efficient and avoids
 * creating many concurrent sockets like the UDP-based executor. You may still
 * want to limit the number of (concurrent) queries in your application or you
 * may be facing rate limitations and bans on the resolver end. For many common
 * applications, you may want to avoid sending the same query multiple times
 * when the first one is still pending, so you will likely want to use this in
 * combination with a `CoopExecutor` like this:
 *
 * ```php
 * $executor = new CoopExecutor(
 *     new TimeoutExecutor(
 *         new TcpTransportExecutor($nameserver),
 *         3.0
 *     )
 * );
 * ```
 *
 * > Internally, this class uses PHP's TCP/IP sockets and does not take advantage
 *   of [react/socket](https://github.com/reactphp/socket) purely for
 *   organizational reasons to avoid a cyclic dependency between the two
 *   packages. Higher-level components should take advantage of the Socket
 *   component instead of reimplementing this socket logic from scratch.
 */
class TcpTransportExecutor implements ExecutorInterface
{
    private $nameserver;
    private $loop;
    private $parser;
    private $dumper;
    /**
     * @var ?resource
     */
    private $socket;
    /**
     * @var Deferred[]
     */
    private $pending = array();
    /**
     * @var string[]
     */
    private $names = array();
    /**
     * Maximum idle time when socket is current unused (i.e. no pending queries outstanding)
     *
     * If a new query is to be sent during the idle period, we can reuse the
     * existing socket without having to wait for a new socket connection.
     * This uses a rather small, hard-coded value to not keep any unneeded
     * sockets open and to not keep the loop busy longer than needed.
     *
     * A future implementation may take advantage of `edns-tcp-keepalive` to keep
     * the socket open for longer periods. This will likely require explicit
     * configuration because this may consume additional resources and also keep
     * the loop busy for longer than expected in some applications.
     *
     * @var float
     * @link https://tools.ietf.org/html/rfc7766#section-6.2.1
     * @link https://tools.ietf.org/html/rfc7828
     */
    private $idlePeriod = 0.001;
    /**
     * @var ?\React\EventLoop\TimerInterface
     */
    private $idleTimer;
    private $writeBuffer = '';
    private $writePending = \false;
    private $readBuffer = '';
    private $readPending = \false;
    /** @var string */
    private $readChunk = 0xffff;
    /**
     * @param string         $nameserver
     * @param ?LoopInterface $loop
     */
    public function __construct($nameserver, $loop = null)
    {
        if (\strpos($nameserver, '[') === \false && \substr_count($nameserver, ':') >= 2 && \strpos($nameserver, '://') === \false) {
            // several colons, but not enclosed in square brackets => enclose IPv6 address in square brackets
            $nameserver = '[' . $nameserver . ']';
        }
        $parts = \parse_url((\strpos($nameserver, '://') === \false ? 'tcp://' : '') . $nameserver);
        if (!isset($parts['scheme'], $parts['host']) || $parts['scheme'] !== 'tcp' || @\inet_pton(\trim($parts['host'], '[]')) === \false) {
            throw new \InvalidArgumentException('Invalid nameserver address given');
        }
        if ($loop !== null && !$loop instanceof LoopInterface) {
            // manual type check to support legacy PHP < 7.1
            throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
        }
        $this->nameserver = 'tcp://' . $parts['host'] . ':' . (isset($parts['port']) ? $parts['port'] : 53);
        $this->loop = $loop ?: Loop::get();
        $this->parser = new Parser();
        $this->dumper = new BinaryDumper();
    }
    public function query(Query $query)
    {
        $request = Message::createRequestForQuery($query);
        // keep shuffing message ID to avoid using the same message ID for two pending queries at the same time
        while (isset($this->pending[$request->id])) {
            $request->id = \mt_rand(0, 0xffff);
            // @codeCoverageIgnore
        }
        $queryData = $this->dumper->toBinary($request);
        $length = \strlen($queryData);
        if ($length > 0xffff) {
            return \NightwatchAgent_kden27khxA4QoEfj\React\Promise\reject(new \RuntimeException('DNS query for ' . $query->describe() . ' failed: Query too large for TCP transport'));
        }
        $queryData = \pack('n', $length) . $queryData;
        if ($this->socket === null) {
            // create async TCP/IP connection (may take a while)
            $socket = @\stream_socket_client($this->nameserver, $errno, $errstr, 0, \STREAM_CLIENT_CONNECT | \STREAM_CLIENT_ASYNC_CONNECT);
            if ($socket === \false) {
                return \NightwatchAgent_kden27khxA4QoEfj\React\Promise\reject(new \RuntimeException('DNS query for ' . $query->describe() . ' failed: Unable to connect to DNS server ' . $this->nameserver . ' (' . $errstr . ')', $errno));
            }
            // set socket to non-blocking and wait for it to become writable (connection success/rejected)
            \stream_set_blocking($socket, \false);
            if (\function_exists('stream_set_chunk_size')) {
                \stream_set_chunk_size($socket, $this->readChunk);
                // @codeCoverageIgnore
            }
            $this->socket = $socket;
        }
        if ($this->idleTimer !== null) {
            $this->loop->cancelTimer($this->idleTimer);
            $this->idleTimer = null;
        }
        // wait for socket to become writable to actually write out data
        $this->writeBuffer .= $queryData;
        if (!$this->writePending) {
            $this->writePending = \true;
            $this->loop->addWriteStream($this->socket, array($this, 'handleWritable'));
        }
        $names =& $this->names;
        $that = $this;
        $deferred = new Deferred(function () use ($that, &$names, $request) {
            // remove from list of pending names, but remember pending query
            $name = $names[$request->id];
            unset($names[$request->id]);
            $that->checkIdle();
            throw new CancellationException('DNS query for ' . $name . ' has been cancelled');
        });
        $this->pending[$request->id] = $deferred;
        $this->names[$request->id] = $query->describe();
        return $deferred->promise();
    }
    /**
     * @internal
     */
    public function handleWritable()
    {
        if ($this->readPending === \false) {
            $name = @\stream_socket_get_name($this->socket, \true);
            if ($name === \false) {
                // Connection failed? Check socket error if available for underlying errno/errstr.
                // @codeCoverageIgnoreStart
                if (\function_exists('socket_import_stream')) {
                    $socket = \socket_import_stream($this->socket);
                    $errno = \socket_get_option($socket, \SOL_SOCKET, \SO_ERROR);
                    $errstr = \socket_strerror($errno);
                } else {
                    $errno = \defined('SOCKET_ECONNREFUSED') ? \SOCKET_ECONNREFUSED : 111;
                    $errstr = 'Connection refused';
                }
                // @codeCoverageIgnoreEnd
                $this->closeError('Unable to connect to DNS server ' . $this->nameserver . ' (' . $errstr . ')', $errno);
                return;
            }
            $this->readPending = \true;
            $this->loop->addReadStream($this->socket, array($this, 'handleRead'));
        }
        $errno = 0;
        $errstr = '';
        \set_error_handler(function ($_, $error) use (&$errno, &$errstr) {
            // Match errstr from PHP's warning message.
            // fwrite(): Send of 327712 bytes failed with errno=32 Broken pipe
            \preg_match('/errno=(\d+) (.+)/', $error, $m);
            $errno = isset($m[1]) ? (int) $m[1] : 0;
            $errstr = isset($m[2]) ? $m[2] : $error;
        });
        $written = \fwrite($this->socket, $this->writeBuffer);
        \restore_error_handler();
        if ($written === \false || $written === 0) {
            $this->closeError('Unable to send query to DNS server ' . $this->nameserver . ' (' . $errstr . ')', $errno);
            return;
        }
        if (isset($this->writeBuffer[$written])) {
            $this->writeBuffer = \substr($this->writeBuffer, $written);
        } else {
            $this->loop->removeWriteStream($this->socket);
            $this->writePending = \false;
            $this->writeBuffer = '';
        }
    }
    /**
     * @internal
     */
    public function handleRead()
    {
        // read one chunk of data from the DNS server
        // any error is fatal, this is a stream of TCP/IP data
        $chunk = @\fread($this->socket, $this->readChunk);
        if ($chunk === \false || $chunk === '') {
            $this->closeError('Connection to DNS server ' . $this->nameserver . ' lost');
            return;
        }
        // reassemble complete message by concatenating all chunks.
        $this->readBuffer .= $chunk;
        // response message header contains at least 12 bytes
        while (isset($this->readBuffer[11])) {
            // read response message length from first 2 bytes and ensure we have length + data in buffer
            list(, $length) = \unpack('n', $this->readBuffer);
            if (!isset($this->readBuffer[$length + 1])) {
                return;
            }
            $data = \substr($this->readBuffer, 2, $length);
            $this->readBuffer = (string) substr($this->readBuffer, $length + 2);
            try {
                $response = $this->parser->parseMessage($data);
            } catch (\Exception $e) {
                // reject all pending queries if we received an invalid message from remote server
                $this->closeError('Invalid message received from DNS server ' . $this->nameserver);
                return;
            }
            // reject all pending queries if we received an unexpected response ID or truncated response
            if (!isset($this->pending[$response->id]) || $response->tc) {
                $this->closeError('Invalid response message received from DNS server ' . $this->nameserver);
                return;
            }
            $deferred = $this->pending[$response->id];
            unset($this->pending[$response->id], $this->names[$response->id]);
            $deferred->resolve($response);
            $this->checkIdle();
        }
    }
    /**
     * @internal
     * @param string $reason
     * @param int    $code
     */
    public function closeError($reason, $code = 0)
    {
        $this->readBuffer = '';
        if ($this->readPending) {
            $this->loop->removeReadStream($this->socket);
            $this->readPending = \false;
        }
        $this->writeBuffer = '';
        if ($this->writePending) {
            $this->loop->removeWriteStream($this->socket);
            $this->writePending = \false;
        }
        if ($this->idleTimer !== null) {
            $this->loop->cancelTimer($this->idleTimer);
            $this->idleTimer = null;
        }
        @\fclose($this->socket);
        $this->socket = null;
        foreach ($this->names as $id => $name) {
            $this->pending[$id]->reject(new \RuntimeException('DNS query for ' . $name . ' failed: ' . $reason, $code));
        }
        $this->pending = $this->names = array();
    }
    /**
     * @internal
     */
    public function checkIdle()
    {
        if ($this->idleTimer === null && !$this->names) {
            $that = $this;
            $this->idleTimer = $this->loop->addTimer($this->idlePeriod, function () use ($that) {
                $that->closeError('Idle timeout');
            });
        }
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query;

final class TimeoutException extends \Exception
{
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query;

use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Loop;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\Promise;
final class TimeoutExecutor implements ExecutorInterface
{
    private $executor;
    private $loop;
    private $timeout;
    /**
     * @param ExecutorInterface $executor
     * @param float $timeout
     * @param ?LoopInterface $loop
     */
    public function __construct(ExecutorInterface $executor, $timeout, $loop = null)
    {
        if ($loop !== null && !$loop instanceof LoopInterface) {
            // manual type check to support legacy PHP < 7.1
            throw new \InvalidArgumentException('Argument #3 ($loop) expected null|React\EventLoop\LoopInterface');
        }
        $this->executor = $executor;
        $this->loop = $loop ?: Loop::get();
        $this->timeout = $timeout;
    }
    public function query(Query $query)
    {
        $promise = $this->executor->query($query);
        $loop = $this->loop;
        $time = $this->timeout;
        return new Promise(function ($resolve, $reject) use ($loop, $time, $promise, $query) {
            $timer = null;
            $promise = $promise->then(function ($v) use (&$timer, $loop, $resolve) {
                if ($timer) {
                    $loop->cancelTimer($timer);
                }
                $timer = \false;
                $resolve($v);
            }, function ($v) use (&$timer, $loop, $reject) {
                if ($timer) {
                    $loop->cancelTimer($timer);
                }
                $timer = \false;
                $reject($v);
            });
            // promise already resolved => no need to start timer
            if ($timer === \false) {
                return;
            }
            // start timeout timer which will cancel the pending promise
            $timer = $loop->addTimer($time, function () use ($time, &$promise, $reject, $query) {
                $reject(new TimeoutException('DNS query for ' . $query->describe() . ' timed out'));
                // Cancel pending query to clean up any underlying resources and references.
                // Avoid garbage references in call stack by passing pending promise by reference.
                assert(\method_exists($promise, 'cancel'));
                $promise->cancel();
                $promise = null;
            });
        }, function () use (&$promise) {
            // Cancelling this promise will cancel the pending query, thus triggering the rejection logic above.
            // Avoid garbage references in call stack by passing pending promise by reference.
            assert(\method_exists($promise, 'cancel'));
            $promise->cancel();
            $promise = null;
        });
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query;

use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Model\Message;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Protocol\BinaryDumper;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Protocol\Parser;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Loop;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\Deferred;
/**
 * Send DNS queries over a UDP transport.
 *
 * This is the main class that sends a DNS query to your DNS server and is used
 * internally by the `Resolver` for the actual message transport.
 *
 * For more advanced usages one can utilize this class directly.
 * The following example looks up the `IPv6` address for `igor.io`.
 *
 * ```php
 * $executor = new UdpTransportExecutor('8.8.8.8:53');
 *
 * $executor->query(
 *     new Query($name, Message::TYPE_AAAA, Message::CLASS_IN)
 * )->then(function (Message $message) {
 *     foreach ($message->answers as $answer) {
 *         echo 'IPv6: ' . $answer->data . PHP_EOL;
 *     }
 * }, 'printf');
 * ```
 *
 * See also the [fourth example](examples).
 *
 * Note that this executor does not implement a timeout, so you will very likely
 * want to use this in combination with a `TimeoutExecutor` like this:
 *
 * ```php
 * $executor = new TimeoutExecutor(
 *     new UdpTransportExecutor($nameserver),
 *     3.0
 * );
 * ```
 *
 * Also note that this executor uses an unreliable UDP transport and that it
 * does not implement any retry logic, so you will likely want to use this in
 * combination with a `RetryExecutor` like this:
 *
 * ```php
 * $executor = new RetryExecutor(
 *     new TimeoutExecutor(
 *         new UdpTransportExecutor($nameserver),
 *         3.0
 *     )
 * );
 * ```
 *
 * Note that this executor is entirely async and as such allows you to execute
 * any number of queries concurrently. You should probably limit the number of
 * concurrent queries in your application or you're very likely going to face
 * rate limitations and bans on the resolver end. For many common applications,
 * you may want to avoid sending the same query multiple times when the first
 * one is still pending, so you will likely want to use this in combination with
 * a `CoopExecutor` like this:
 *
 * ```php
 * $executor = new CoopExecutor(
 *     new RetryExecutor(
 *         new TimeoutExecutor(
 *             new UdpTransportExecutor($nameserver),
 *             3.0
 *         )
 *     )
 * );
 * ```
 *
 * > Internally, this class uses PHP's UDP sockets and does not take advantage
 *   of [react/datagram](https://github.com/reactphp/datagram) purely for
 *   organizational reasons to avoid a cyclic dependency between the two
 *   packages. Higher-level components should take advantage of the Datagram
 *   component instead of reimplementing this socket logic from scratch.
 */
final class UdpTransportExecutor implements ExecutorInterface
{
    private $nameserver;
    private $loop;
    private $parser;
    private $dumper;
    /**
     * maximum UDP packet size to send and receive
     *
     * @var int
     */
    private $maxPacketSize = 512;
    /**
     * @param string         $nameserver
     * @param ?LoopInterface $loop
     */
    public function __construct($nameserver, $loop = null)
    {
        if (\strpos($nameserver, '[') === \false && \substr_count($nameserver, ':') >= 2 && \strpos($nameserver, '://') === \false) {
            // several colons, but not enclosed in square brackets => enclose IPv6 address in square brackets
            $nameserver = '[' . $nameserver . ']';
        }
        $parts = \parse_url((\strpos($nameserver, '://') === \false ? 'udp://' : '') . $nameserver);
        if (!isset($parts['scheme'], $parts['host']) || $parts['scheme'] !== 'udp' || @\inet_pton(\trim($parts['host'], '[]')) === \false) {
            throw new \InvalidArgumentException('Invalid nameserver address given');
        }
        if ($loop !== null && !$loop instanceof LoopInterface) {
            // manual type check to support legacy PHP < 7.1
            throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
        }
        $this->nameserver = 'udp://' . $parts['host'] . ':' . (isset($parts['port']) ? $parts['port'] : 53);
        $this->loop = $loop ?: Loop::get();
        $this->parser = new Parser();
        $this->dumper = new BinaryDumper();
    }
    public function query(Query $query)
    {
        $request = Message::createRequestForQuery($query);
        $queryData = $this->dumper->toBinary($request);
        if (isset($queryData[$this->maxPacketSize])) {
            return \NightwatchAgent_kden27khxA4QoEfj\React\Promise\reject(new \RuntimeException('DNS query for ' . $query->describe() . ' failed: Query too large for UDP transport', \defined('SOCKET_EMSGSIZE') ? \SOCKET_EMSGSIZE : 90));
        }
        // UDP connections are instant, so try connection without a loop or timeout
        $errno = 0;
        $errstr = '';
        $socket = @\stream_socket_client($this->nameserver, $errno, $errstr, 0);
        if ($socket === \false) {
            return \NightwatchAgent_kden27khxA4QoEfj\React\Promise\reject(new \RuntimeException('DNS query for ' . $query->describe() . ' failed: Unable to connect to DNS server ' . $this->nameserver . ' (' . $errstr . ')', $errno));
        }
        // set socket to non-blocking and immediately try to send (fill write buffer)
        \stream_set_blocking($socket, \false);
        \set_error_handler(function ($_, $error) use (&$errno, &$errstr) {
            // Write may potentially fail, but most common errors are already caught by connection check above.
            // Among others, macOS is known to report here when trying to send to broadcast address.
            // This can also be reproduced by writing data exceeding `stream_set_chunk_size()` to a server refusing UDP data.
            // fwrite(): send of 8192 bytes failed with errno=111 Connection refused
            \preg_match('/errno=(\d+) (.+)/', $error, $m);
            $errno = isset($m[1]) ? (int) $m[1] : 0;
            $errstr = isset($m[2]) ? $m[2] : $error;
        });
        $written = \fwrite($socket, $queryData);
        \restore_error_handler();
        if ($written !== \strlen($queryData)) {
            return \NightwatchAgent_kden27khxA4QoEfj\React\Promise\reject(new \RuntimeException('DNS query for ' . $query->describe() . ' failed: Unable to send query to DNS server ' . $this->nameserver . ' (' . $errstr . ')', $errno));
        }
        $loop = $this->loop;
        $deferred = new Deferred(function () use ($loop, $socket, $query) {
            // cancellation should remove socket from loop and close socket
            $loop->removeReadStream($socket);
            \fclose($socket);
            throw new CancellationException('DNS query for ' . $query->describe() . ' has been cancelled');
        });
        $max = $this->maxPacketSize;
        $parser = $this->parser;
        $nameserver = $this->nameserver;
        $loop->addReadStream($socket, function ($socket) use ($loop, $deferred, $query, $parser, $request, $max, $nameserver) {
            // try to read a single data packet from the DNS server
            // ignoring any errors, this is uses UDP packets and not a stream of data
            $data = @\fread($socket, $max);
            if ($data === \false) {
                return;
            }
            try {
                $response = $parser->parseMessage($data);
            } catch (\Exception $e) {
                // ignore and await next if we received an invalid message from remote server
                // this may as well be a fake response from an attacker (possible DOS)
                return;
            }
            // ignore and await next if we received an unexpected response ID
            // this may as well be a fake response from an attacker (possible cache poisoning)
            if ($response->id !== $request->id) {
                return;
            }
            // we only react to the first valid message, so remove socket from loop and close
            $loop->removeReadStream($socket);
            \fclose($socket);
            if ($response->tc) {
                $deferred->reject(new \RuntimeException('DNS query for ' . $query->describe() . ' failed: The DNS server ' . $nameserver . ' returned a truncated result for a UDP query', \defined('SOCKET_EMSGSIZE') ? \SOCKET_EMSGSIZE : 90));
                return;
            }
            $deferred->resolve($response);
        });
        return $deferred->promise();
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns;

final class RecordNotFoundException extends \Exception
{
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns\Resolver;

use NightwatchAgent_kden27khxA4QoEfj\React\Cache\ArrayCache;
use NightwatchAgent_kden27khxA4QoEfj\React\Cache\CacheInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Config\Config;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Config\HostsFile;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query\CachingExecutor;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query\CoopExecutor;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query\ExecutorInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query\FallbackExecutor;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query\HostsFileExecutor;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query\RetryExecutor;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query\SelectiveTransportExecutor;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query\TcpTransportExecutor;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query\TimeoutExecutor;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query\UdpTransportExecutor;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Loop;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
final class Factory
{
    /**
     * Creates a DNS resolver instance for the given DNS config
     *
     * As of v1.7.0 it's recommended to pass a `Config` object instead of a
     * single nameserver address. If the given config contains more than one DNS
     * nameserver, all DNS nameservers will be used in order. The primary DNS
     * server will always be used first before falling back to the secondary or
     * tertiary DNS server.
     *
     * @param Config|string  $config DNS Config object (recommended) or single nameserver address
     * @param ?LoopInterface $loop
     * @return \React\Dns\Resolver\ResolverInterface
     * @throws \InvalidArgumentException for invalid DNS server address
     * @throws \UnderflowException when given DNS Config object has an empty list of nameservers
     */
    public function create($config, $loop = null)
    {
        if ($loop !== null && !$loop instanceof LoopInterface) {
            // manual type check to support legacy PHP < 7.1
            throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
        }
        $executor = $this->decorateHostsFileExecutor($this->createExecutor($config, $loop ?: Loop::get()));
        return new Resolver($executor);
    }
    /**
     * Creates a cached DNS resolver instance for the given DNS config and cache
     *
     * As of v1.7.0 it's recommended to pass a `Config` object instead of a
     * single nameserver address. If the given config contains more than one DNS
     * nameserver, all DNS nameservers will be used in order. The primary DNS
     * server will always be used first before falling back to the secondary or
     * tertiary DNS server.
     *
     * @param Config|string   $config DNS Config object (recommended) or single nameserver address
     * @param ?LoopInterface  $loop
     * @param ?CacheInterface $cache
     * @return \React\Dns\Resolver\ResolverInterface
     * @throws \InvalidArgumentException for invalid DNS server address
     * @throws \UnderflowException when given DNS Config object has an empty list of nameservers
     */
    public function createCached($config, $loop = null, $cache = null)
    {
        if ($loop !== null && !$loop instanceof LoopInterface) {
            // manual type check to support legacy PHP < 7.1
            throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
        }
        if ($cache !== null && !$cache instanceof CacheInterface) {
            // manual type check to support legacy PHP < 7.1
            throw new \InvalidArgumentException('Argument #3 ($cache) expected null|React\Cache\CacheInterface');
        }
        // default to keeping maximum of 256 responses in cache unless explicitly given
        if (!$cache instanceof CacheInterface) {
            $cache = new ArrayCache(256);
        }
        $executor = $this->createExecutor($config, $loop ?: Loop::get());
        $executor = new CachingExecutor($executor, $cache);
        $executor = $this->decorateHostsFileExecutor($executor);
        return new Resolver($executor);
    }
    /**
     * Tries to load the hosts file and decorates the given executor on success
     *
     * @param ExecutorInterface $executor
     * @return ExecutorInterface
     * @codeCoverageIgnore
     */
    private function decorateHostsFileExecutor(ExecutorInterface $executor)
    {
        try {
            $executor = new HostsFileExecutor(HostsFile::loadFromPathBlocking(), $executor);
        } catch (\RuntimeException $e) {
            // ignore this file if it can not be loaded
        }
        // Windows does not store localhost in hosts file by default but handles this internally
        // To compensate for this, we explicitly use hard-coded defaults for localhost
        if (\DIRECTORY_SEPARATOR === '\\') {
            $executor = new HostsFileExecutor(new HostsFile("127.0.0.1 localhost\n::1 localhost"), $executor);
        }
        return $executor;
    }
    /**
     * @param Config|string $nameserver
     * @param LoopInterface $loop
     * @return CoopExecutor
     * @throws \InvalidArgumentException for invalid DNS server address
     * @throws \UnderflowException when given DNS Config object has an empty list of nameservers
     */
    private function createExecutor($nameserver, LoopInterface $loop)
    {
        if ($nameserver instanceof Config) {
            if (!$nameserver->nameservers) {
                throw new \UnderflowException('Empty config with no DNS servers');
            }
            // Hard-coded to check up to 3 DNS servers to match default limits in place in most systems (see MAXNS config).
            // Note to future self: Recursion isn't too hard, but how deep do we really want to go?
            $primary = reset($nameserver->nameservers);
            $secondary = next($nameserver->nameservers);
            $tertiary = next($nameserver->nameservers);
            if ($tertiary !== \false) {
                // 3 DNS servers given => nest first with fallback for second and third
                return new CoopExecutor(new RetryExecutor(new FallbackExecutor($this->createSingleExecutor($primary, $loop), new FallbackExecutor($this->createSingleExecutor($secondary, $loop), $this->createSingleExecutor($tertiary, $loop)))));
            } elseif ($secondary !== \false) {
                // 2 DNS servers given => fallback from first to second
                return new CoopExecutor(new RetryExecutor(new FallbackExecutor($this->createSingleExecutor($primary, $loop), $this->createSingleExecutor($secondary, $loop))));
            } else {
                // 1 DNS server given => use single executor
                $nameserver = $primary;
            }
        }
        return new CoopExecutor(new RetryExecutor($this->createSingleExecutor($nameserver, $loop)));
    }
    /**
     * @param string $nameserver
     * @param LoopInterface $loop
     * @return ExecutorInterface
     * @throws \InvalidArgumentException for invalid DNS server address
     */
    private function createSingleExecutor($nameserver, LoopInterface $loop)
    {
        $parts = \parse_url($nameserver);
        if (isset($parts['scheme']) && $parts['scheme'] === 'tcp') {
            $executor = $this->createTcpExecutor($nameserver, $loop);
        } elseif (isset($parts['scheme']) && $parts['scheme'] === 'udp') {
            $executor = $this->createUdpExecutor($nameserver, $loop);
        } else {
            $executor = new SelectiveTransportExecutor($this->createUdpExecutor($nameserver, $loop), $this->createTcpExecutor($nameserver, $loop));
        }
        return $executor;
    }
    /**
     * @param string $nameserver
     * @param LoopInterface $loop
     * @return TimeoutExecutor
     * @throws \InvalidArgumentException for invalid DNS server address
     */
    private function createTcpExecutor($nameserver, LoopInterface $loop)
    {
        return new TimeoutExecutor(new TcpTransportExecutor($nameserver, $loop), 5.0, $loop);
    }
    /**
     * @param string $nameserver
     * @param LoopInterface $loop
     * @return TimeoutExecutor
     * @throws \InvalidArgumentException for invalid DNS server address
     */
    private function createUdpExecutor($nameserver, LoopInterface $loop)
    {
        return new TimeoutExecutor(new UdpTransportExecutor($nameserver, $loop), 5.0, $loop);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns\Resolver;

use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Model\Message;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query\ExecutorInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Query\Query;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\RecordNotFoundException;
/**
 * @see ResolverInterface for the base interface
 */
final class Resolver implements ResolverInterface
{
    private $executor;
    public function __construct(ExecutorInterface $executor)
    {
        $this->executor = $executor;
    }
    public function resolve($domain)
    {
        return $this->resolveAll($domain, Message::TYPE_A)->then(function (array $ips) {
            return $ips[array_rand($ips)];
        });
    }
    public function resolveAll($domain, $type)
    {
        $query = new Query($domain, $type, Message::CLASS_IN);
        $that = $this;
        return $this->executor->query($query)->then(function (Message $response) use ($query, $that) {
            return $that->extractValues($query, $response);
        });
    }
    /**
     * [Internal] extract all resource record values from response for this query
     *
     * @param Query   $query
     * @param Message $response
     * @return array
     * @throws RecordNotFoundException when response indicates an error or contains no data
     * @internal
     */
    public function extractValues(Query $query, Message $response)
    {
        // reject if response code indicates this is an error response message
        $code = $response->rcode;
        if ($code !== Message::RCODE_OK) {
            switch ($code) {
                case Message::RCODE_FORMAT_ERROR:
                    $message = 'Format Error';
                    break;
                case Message::RCODE_SERVER_FAILURE:
                    $message = 'Server Failure';
                    break;
                case Message::RCODE_NAME_ERROR:
                    $message = 'Non-Existent Domain / NXDOMAIN';
                    break;
                case Message::RCODE_NOT_IMPLEMENTED:
                    $message = 'Not Implemented';
                    break;
                case Message::RCODE_REFUSED:
                    $message = 'Refused';
                    break;
                default:
                    $message = 'Unknown error response code ' . $code;
            }
            throw new RecordNotFoundException('DNS query for ' . $query->describe() . ' returned an error response (' . $message . ')', $code);
        }
        $answers = $response->answers;
        $addresses = $this->valuesByNameAndType($answers, $query->name, $query->type);
        // reject if we did not receive a valid answer (domain is valid, but no record for this type could be found)
        if (0 === count($addresses)) {
            throw new RecordNotFoundException('DNS query for ' . $query->describe() . ' did not return a valid answer (NOERROR / NODATA)');
        }
        return array_values($addresses);
    }
    /**
     * @param \React\Dns\Model\Record[] $answers
     * @param string                    $name
     * @param int                       $type
     * @return array
     */
    private function valuesByNameAndType(array $answers, $name, $type)
    {
        // return all record values for this name and type (if any)
        $named = $this->filterByName($answers, $name);
        $records = $this->filterByType($named, $type);
        if ($records) {
            return $this->mapRecordData($records);
        }
        // no matching records found? check if there are any matching CNAMEs instead
        $cnameRecords = $this->filterByType($named, Message::TYPE_CNAME);
        if ($cnameRecords) {
            $cnames = $this->mapRecordData($cnameRecords);
            foreach ($cnames as $cname) {
                $records = array_merge($records, $this->valuesByNameAndType($answers, $cname, $type));
            }
        }
        return $records;
    }
    private function filterByName(array $answers, $name)
    {
        return $this->filterByField($answers, 'name', $name);
    }
    private function filterByType(array $answers, $type)
    {
        return $this->filterByField($answers, 'type', $type);
    }
    private function filterByField(array $answers, $field, $value)
    {
        $value = strtolower($value);
        return array_filter($answers, function ($answer) use ($field, $value) {
            return $value === strtolower($answer->{$field});
        });
    }
    private function mapRecordData(array $records)
    {
        return array_map(function ($record) {
            return $record->data;
        }, $records);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Dns\Resolver;

interface ResolverInterface
{
    /**
     * Resolves the given $domain name to a single IPv4 address (type `A` query).
     *
     * ```php
     * $resolver->resolve('reactphp.org')->then(function ($ip) {
     *     echo 'IP for reactphp.org is ' . $ip . PHP_EOL;
     * });
     * ```
     *
     * This is one of the main methods in this package. It sends a DNS query
     * for the given $domain name to your DNS server and returns a single IP
     * address on success.
     *
     * If the DNS server sends a DNS response message that contains more than
     * one IP address for this query, it will randomly pick one of the IP
     * addresses from the response. If you want the full list of IP addresses
     * or want to send a different type of query, you should use the
     * [`resolveAll()`](#resolveall) method instead.
     *
     * If the DNS server sends a DNS response message that indicates an error
     * code, this method will reject with a `RecordNotFoundException`. Its
     * message and code can be used to check for the response code.
     *
     * If the DNS communication fails and the server does not respond with a
     * valid response message, this message will reject with an `Exception`.
     *
     * Pending DNS queries can be cancelled by cancelling its pending promise like so:
     *
     * ```php
     * $promise = $resolver->resolve('reactphp.org');
     *
     * $promise->cancel();
     * ```
     *
     * @param string $domain
     * @return \React\Promise\PromiseInterface<string>
     *     resolves with a single IP address on success or rejects with an Exception on error.
     */
    public function resolve($domain);
    /**
     * Resolves all record values for the given $domain name and query $type.
     *
     * ```php
     * $resolver->resolveAll('reactphp.org', Message::TYPE_A)->then(function ($ips) {
     *     echo 'IPv4 addresses for reactphp.org ' . implode(', ', $ips) . PHP_EOL;
     * });
     *
     * $resolver->resolveAll('reactphp.org', Message::TYPE_AAAA)->then(function ($ips) {
     *     echo 'IPv6 addresses for reactphp.org ' . implode(', ', $ips) . PHP_EOL;
     * });
     * ```
     *
     * This is one of the main methods in this package. It sends a DNS query
     * for the given $domain name to your DNS server and returns a list with all
     * record values on success.
     *
     * If the DNS server sends a DNS response message that contains one or more
     * records for this query, it will return a list with all record values
     * from the response. You can use the `Message::TYPE_*` constants to control
     * which type of query will be sent. Note that this method always returns a
     * list of record values, but each record value type depends on the query
     * type. For example, it returns the IPv4 addresses for type `A` queries,
     * the IPv6 addresses for type `AAAA` queries, the hostname for type `NS`,
     * `CNAME` and `PTR` queries and structured data for other queries. See also
     * the `Record` documentation for more details.
     *
     * If the DNS server sends a DNS response message that indicates an error
     * code, this method will reject with a `RecordNotFoundException`. Its
     * message and code can be used to check for the response code.
     *
     * If the DNS communication fails and the server does not respond with a
     * valid response message, this message will reject with an `Exception`.
     *
     * Pending DNS queries can be cancelled by cancelling its pending promise like so:
     *
     * ```php
     * $promise = $resolver->resolveAll('reactphp.org', Message::TYPE_AAAA);
     *
     * $promise->cancel();
     * ```
     *
     * @param string $domain
     * @return \React\Promise\PromiseInterface<array>
     *     Resolves with all record values on success or rejects with an Exception on error.
     */
    public function resolveAll($domain, $type);
}
The MIT License (MIT)

Copyright (c) 2012 Christian Lück, Cees-Jan Kiewiet, Jan Sorgalla, Chris Boden, Igor Wiedler

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\EventLoop;

use Ev;
use EvIo;
use EvLoop;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Tick\FutureTickQueue;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Timer\Timer;
use SplObjectStorage;
/**
 * An `ext-ev` based event loop.
 *
 * This loop uses the [`ev` PECL extension](https://pecl.php.net/package/ev),
 * that provides an interface to `libev` library.
 * `libev` itself supports a number of system-specific backends (epoll, kqueue).
 *
 * This loop is known to work with PHP 5.4 through PHP 8+.
 *
 * @see http://php.net/manual/en/book.ev.php
 * @see https://bitbucket.org/osmanov/pecl-ev/overview
 */
class ExtEvLoop implements LoopInterface
{
    /**
     * @var EvLoop
     */
    private $loop;
    /**
     * @var FutureTickQueue
     */
    private $futureTickQueue;
    /**
     * @var SplObjectStorage
     */
    private $timers;
    /**
     * @var EvIo[]
     */
    private $readStreams = array();
    /**
     * @var EvIo[]
     */
    private $writeStreams = array();
    /**
     * @var bool
     */
    private $running;
    /**
     * @var SignalsHandler
     */
    private $signals;
    /**
     * @var \EvSignal[]
     */
    private $signalEvents = array();
    public function __construct()
    {
        $this->loop = new EvLoop();
        $this->futureTickQueue = new FutureTickQueue();
        $this->timers = new SplObjectStorage();
        $this->signals = new SignalsHandler();
    }
    public function addReadStream($stream, $listener)
    {
        $key = (int) $stream;
        if (isset($this->readStreams[$key])) {
            return;
        }
        $callback = $this->getStreamListenerClosure($stream, $listener);
        $event = $this->loop->io($stream, Ev::READ, $callback);
        $this->readStreams[$key] = $event;
    }
    /**
     * @param resource $stream
     * @param callable $listener
     *
     * @return \Closure
     */
    private function getStreamListenerClosure($stream, $listener)
    {
        return function () use ($stream, $listener) {
            \call_user_func($listener, $stream);
        };
    }
    public function addWriteStream($stream, $listener)
    {
        $key = (int) $stream;
        if (isset($this->writeStreams[$key])) {
            return;
        }
        $callback = $this->getStreamListenerClosure($stream, $listener);
        $event = $this->loop->io($stream, Ev::WRITE, $callback);
        $this->writeStreams[$key] = $event;
    }
    public function removeReadStream($stream)
    {
        $key = (int) $stream;
        if (!isset($this->readStreams[$key])) {
            return;
        }
        $this->readStreams[$key]->stop();
        unset($this->readStreams[$key]);
    }
    public function removeWriteStream($stream)
    {
        $key = (int) $stream;
        if (!isset($this->writeStreams[$key])) {
            return;
        }
        $this->writeStreams[$key]->stop();
        unset($this->writeStreams[$key]);
    }
    public function addTimer($interval, $callback)
    {
        $timer = new Timer($interval, $callback, \false);
        $that = $this;
        $timers = $this->timers;
        $callback = function () use ($timer, $timers, $that) {
            \call_user_func($timer->getCallback(), $timer);
            if ($timers->offsetExists($timer)) {
                $that->cancelTimer($timer);
            }
        };
        $event = $this->loop->timer($timer->getInterval(), 0.0, $callback);
        $this->timers->offsetSet($timer, $event);
        return $timer;
    }
    public function addPeriodicTimer($interval, $callback)
    {
        $timer = new Timer($interval, $callback, \true);
        $callback = function () use ($timer) {
            \call_user_func($timer->getCallback(), $timer);
        };
        $event = $this->loop->timer($timer->getInterval(), $timer->getInterval(), $callback);
        $this->timers->offsetSet($timer, $event);
        return $timer;
    }
    public function cancelTimer(TimerInterface $timer)
    {
        if (!isset($this->timers[$timer])) {
            return;
        }
        $event = $this->timers[$timer];
        $event->stop();
        $this->timers->offsetUnset($timer);
    }
    public function futureTick($listener)
    {
        $this->futureTickQueue->add($listener);
    }
    public function run()
    {
        $this->running = \true;
        while ($this->running) {
            $this->futureTickQueue->tick();
            $hasPendingCallbacks = !$this->futureTickQueue->isEmpty();
            $wasJustStopped = !$this->running;
            $nothingLeftToDo = !$this->readStreams && !$this->writeStreams && !$this->timers->count() && $this->signals->isEmpty();
            $flags = Ev::RUN_ONCE;
            if ($wasJustStopped || $hasPendingCallbacks) {
                $flags |= Ev::RUN_NOWAIT;
            } elseif ($nothingLeftToDo) {
                break;
            }
            $this->loop->run($flags);
        }
    }
    public function stop()
    {
        $this->running = \false;
    }
    public function __destruct()
    {
        /** @var TimerInterface $timer */
        foreach ($this->timers as $timer) {
            $this->cancelTimer($timer);
        }
        foreach ($this->readStreams as $key => $stream) {
            $this->removeReadStream($key);
        }
        foreach ($this->writeStreams as $key => $stream) {
            $this->removeWriteStream($key);
        }
    }
    public function addSignal($signal, $listener)
    {
        $this->signals->add($signal, $listener);
        if (!isset($this->signalEvents[$signal])) {
            $this->signalEvents[$signal] = $this->loop->signal($signal, function () use ($signal) {
                $this->signals->call($signal);
            });
        }
    }
    public function removeSignal($signal, $listener)
    {
        $this->signals->remove($signal, $listener);
        if (isset($this->signalEvents[$signal])) {
            $this->signalEvents[$signal]->stop();
            unset($this->signalEvents[$signal]);
        }
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\EventLoop;

use BadMethodCallException;
use Event;
use EventBase;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Tick\FutureTickQueue;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Timer\Timer;
use SplObjectStorage;
/**
 * An `ext-event` based event loop.
 *
 * This uses the [`event` PECL extension](https://pecl.php.net/package/event),
 * that provides an interface to `libevent` library.
 * `libevent` itself supports a number of system-specific backends (epoll, kqueue).
 *
 * This loop is known to work with PHP 5.4 through PHP 8+.
 *
 * @link https://pecl.php.net/package/event
 */
final class ExtEventLoop implements LoopInterface
{
    private $eventBase;
    private $futureTickQueue;
    private $timerCallback;
    private $timerEvents;
    private $streamCallback;
    private $readEvents = array();
    private $writeEvents = array();
    private $readListeners = array();
    private $writeListeners = array();
    private $readRefs = array();
    private $writeRefs = array();
    private $running;
    private $signals;
    private $signalEvents = array();
    public function __construct()
    {
        if (!\class_exists('EventBase', \false)) {
            throw new BadMethodCallException('Cannot create ExtEventLoop, ext-event extension missing');
        }
        // support arbitrary file descriptors and not just sockets
        // Windows only has limited file descriptor support, so do not require this (will fail otherwise)
        // @link http://www.wangafu.net/~nickm/libevent-book/Ref2_eventbase.html#_setting_up_a_complicated_event_base
        $config = new \EventConfig();
        if (\DIRECTORY_SEPARATOR !== '\\') {
            $config->requireFeatures(\EventConfig::FEATURE_FDS);
        }
        $this->eventBase = new EventBase($config);
        $this->futureTickQueue = new FutureTickQueue();
        $this->timerEvents = new SplObjectStorage();
        $this->signals = new SignalsHandler();
        $this->createTimerCallback();
        $this->createStreamCallback();
    }
    public function __destruct()
    {
        // explicitly clear all references to Event objects to prevent SEGFAULTs on Windows
        foreach ($this->timerEvents as $timer) {
            $this->timerEvents->offsetUnset($timer);
        }
        $this->readEvents = array();
        $this->writeEvents = array();
    }
    public function addReadStream($stream, $listener)
    {
        $key = (int) $stream;
        if (isset($this->readListeners[$key])) {
            return;
        }
        $event = new Event($this->eventBase, $stream, Event::PERSIST | Event::READ, $this->streamCallback);
        $event->add();
        $this->readEvents[$key] = $event;
        $this->readListeners[$key] = $listener;
        // ext-event does not increase refcount on stream resources for PHP 7+
        // manually keep track of stream resource to prevent premature garbage collection
        if (\PHP_VERSION_ID >= 70000) {
            $this->readRefs[$key] = $stream;
        }
    }
    public function addWriteStream($stream, $listener)
    {
        $key = (int) $stream;
        if (isset($this->writeListeners[$key])) {
            return;
        }
        $event = new Event($this->eventBase, $stream, Event::PERSIST | Event::WRITE, $this->streamCallback);
        $event->add();
        $this->writeEvents[$key] = $event;
        $this->writeListeners[$key] = $listener;
        // ext-event does not increase refcount on stream resources for PHP 7+
        // manually keep track of stream resource to prevent premature garbage collection
        if (\PHP_VERSION_ID >= 70000) {
            $this->writeRefs[$key] = $stream;
        }
    }
    public function removeReadStream($stream)
    {
        $key = (int) $stream;
        if (isset($this->readEvents[$key])) {
            $this->readEvents[$key]->free();
            unset($this->readEvents[$key], $this->readListeners[$key], $this->readRefs[$key]);
        }
    }
    public function removeWriteStream($stream)
    {
        $key = (int) $stream;
        if (isset($this->writeEvents[$key])) {
            $this->writeEvents[$key]->free();
            unset($this->writeEvents[$key], $this->writeListeners[$key], $this->writeRefs[$key]);
        }
    }
    public function addTimer($interval, $callback)
    {
        $timer = new Timer($interval, $callback, \false);
        $this->scheduleTimer($timer);
        return $timer;
    }
    public function addPeriodicTimer($interval, $callback)
    {
        $timer = new Timer($interval, $callback, \true);
        $this->scheduleTimer($timer);
        return $timer;
    }
    public function cancelTimer(TimerInterface $timer)
    {
        if ($this->timerEvents->offsetExists($timer)) {
            $this->timerEvents[$timer]->free();
            $this->timerEvents->offsetUnset($timer);
        }
    }
    public function futureTick($listener)
    {
        $this->futureTickQueue->add($listener);
    }
    public function addSignal($signal, $listener)
    {
        $this->signals->add($signal, $listener);
        if (!isset($this->signalEvents[$signal])) {
            $this->signalEvents[$signal] = Event::signal($this->eventBase, $signal, array($this->signals, 'call'));
            $this->signalEvents[$signal]->add();
        }
    }
    public function removeSignal($signal, $listener)
    {
        $this->signals->remove($signal, $listener);
        if (isset($this->signalEvents[$signal]) && $this->signals->count($signal) === 0) {
            $this->signalEvents[$signal]->free();
            unset($this->signalEvents[$signal]);
        }
    }
    public function run()
    {
        $this->running = \true;
        while ($this->running) {
            $this->futureTickQueue->tick();
            $flags = EventBase::LOOP_ONCE;
            if (!$this->running || !$this->futureTickQueue->isEmpty()) {
                $flags |= EventBase::LOOP_NONBLOCK;
            } elseif (!$this->readEvents && !$this->writeEvents && !$this->timerEvents->count() && $this->signals->isEmpty()) {
                break;
            }
            $this->eventBase->loop($flags);
        }
    }
    public function stop()
    {
        $this->running = \false;
    }
    /**
     * Schedule a timer for execution.
     *
     * @param TimerInterface $timer
     */
    private function scheduleTimer(TimerInterface $timer)
    {
        $flags = Event::TIMEOUT;
        if ($timer->isPeriodic()) {
            $flags |= Event::PERSIST;
        }
        $event = new Event($this->eventBase, -1, $flags, $this->timerCallback, $timer);
        $this->timerEvents[$timer] = $event;
        $event->add($timer->getInterval());
    }
    /**
     * Create a callback used as the target of timer events.
     *
     * A reference is kept to the callback for the lifetime of the loop
     * to prevent "Cannot destroy active lambda function" fatal error from
     * the event extension.
     */
    private function createTimerCallback()
    {
        $timers = $this->timerEvents;
        $this->timerCallback = function ($_, $__, $timer) use ($timers) {
            \call_user_func($timer->getCallback(), $timer);
            if (!$timer->isPeriodic() && $timers->offsetExists($timer)) {
                $this->cancelTimer($timer);
            }
        };
    }
    /**
     * Create a callback used as the target of stream events.
     *
     * A reference is kept to the callback for the lifetime of the loop
     * to prevent "Cannot destroy active lambda function" fatal error from
     * the event extension.
     */
    private function createStreamCallback()
    {
        $read =& $this->readListeners;
        $write =& $this->writeListeners;
        $this->streamCallback = function ($stream, $flags) use (&$read, &$write) {
            $key = (int) $stream;
            if (Event::READ === (Event::READ & $flags) && isset($read[$key])) {
                \call_user_func($read[$key], $stream);
            }
            if (Event::WRITE === (Event::WRITE & $flags) && isset($write[$key])) {
                \call_user_func($write[$key], $stream);
            }
        };
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\EventLoop;

use BadMethodCallException;
use NightwatchAgent_kden27khxA4QoEfj\libev\EventLoop;
use NightwatchAgent_kden27khxA4QoEfj\libev\IOEvent;
use NightwatchAgent_kden27khxA4QoEfj\libev\SignalEvent;
use NightwatchAgent_kden27khxA4QoEfj\libev\TimerEvent;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Tick\FutureTickQueue;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Timer\Timer;
use SplObjectStorage;
/**
 * [Deprecated] An `ext-libev` based event loop.
 *
 * This uses an [unofficial `libev` extension](https://github.com/m4rw3r/php-libev),
 * that provides an interface to `libev` library.
 * `libev` itself supports a number of system-specific backends (epoll, kqueue).
 *
 * This loop does only work with PHP 5.
 * An update for PHP 7 is [unlikely](https://github.com/m4rw3r/php-libev/issues/8)
 * to happen any time soon.
 *
 * @see https://github.com/m4rw3r/php-libev
 * @see https://gist.github.com/1688204
 * @deprecated 1.2.0, use [`ExtEvLoop`](#extevloop) instead.
 */
final class ExtLibevLoop implements LoopInterface
{
    private $loop;
    private $futureTickQueue;
    private $timerEvents;
    private $readEvents = array();
    private $writeEvents = array();
    private $running;
    private $signals;
    private $signalEvents = array();
    public function __construct()
    {
        if (!\class_exists('NightwatchAgent_kden27khxA4QoEfj\libev\EventLoop', \false)) {
            throw new BadMethodCallException('Cannot create ExtLibevLoop, ext-libev extension missing');
        }
        $this->loop = new EventLoop();
        $this->futureTickQueue = new FutureTickQueue();
        $this->timerEvents = new SplObjectStorage();
        $this->signals = new SignalsHandler();
    }
    public function addReadStream($stream, $listener)
    {
        if (isset($this->readEvents[(int) $stream])) {
            return;
        }
        $callback = function () use ($stream, $listener) {
            \call_user_func($listener, $stream);
        };
        $event = new IOEvent($callback, $stream, IOEvent::READ);
        $this->loop->add($event);
        $this->readEvents[(int) $stream] = $event;
    }
    public function addWriteStream($stream, $listener)
    {
        if (isset($this->writeEvents[(int) $stream])) {
            return;
        }
        $callback = function () use ($stream, $listener) {
            \call_user_func($listener, $stream);
        };
        $event = new IOEvent($callback, $stream, IOEvent::WRITE);
        $this->loop->add($event);
        $this->writeEvents[(int) $stream] = $event;
    }
    public function removeReadStream($stream)
    {
        $key = (int) $stream;
        if (isset($this->readEvents[$key])) {
            $this->readEvents[$key]->stop();
            $this->loop->remove($this->readEvents[$key]);
            unset($this->readEvents[$key]);
        }
    }
    public function removeWriteStream($stream)
    {
        $key = (int) $stream;
        if (isset($this->writeEvents[$key])) {
            $this->writeEvents[$key]->stop();
            $this->loop->remove($this->writeEvents[$key]);
            unset($this->writeEvents[$key]);
        }
    }
    public function addTimer($interval, $callback)
    {
        $timer = new Timer($interval, $callback, \false);
        $that = $this;
        $timers = $this->timerEvents;
        $callback = function () use ($timer, $timers, $that) {
            \call_user_func($timer->getCallback(), $timer);
            if ($timers->contains($timer)) {
                $that->cancelTimer($timer);
            }
        };
        $event = new TimerEvent($callback, $timer->getInterval());
        $this->timerEvents->attach($timer, $event);
        $this->loop->add($event);
        return $timer;
    }
    public function addPeriodicTimer($interval, $callback)
    {
        $timer = new Timer($interval, $callback, \true);
        $callback = function () use ($timer) {
            \call_user_func($timer->getCallback(), $timer);
        };
        $event = new TimerEvent($callback, $timer->getInterval(), $timer->getInterval());
        $this->timerEvents->attach($timer, $event);
        $this->loop->add($event);
        return $timer;
    }
    public function cancelTimer(TimerInterface $timer)
    {
        if (isset($this->timerEvents[$timer])) {
            $this->loop->remove($this->timerEvents[$timer]);
            $this->timerEvents->detach($timer);
        }
    }
    public function futureTick($listener)
    {
        $this->futureTickQueue->add($listener);
    }
    public function addSignal($signal, $listener)
    {
        $this->signals->add($signal, $listener);
        if (!isset($this->signalEvents[$signal])) {
            $signals = $this->signals;
            $this->signalEvents[$signal] = new SignalEvent(function () use ($signals, $signal) {
                $signals->call($signal);
            }, $signal);
            $this->loop->add($this->signalEvents[$signal]);
        }
    }
    public function removeSignal($signal, $listener)
    {
        $this->signals->remove($signal, $listener);
        if (isset($this->signalEvents[$signal]) && $this->signals->count($signal) === 0) {
            $this->signalEvents[$signal]->stop();
            $this->loop->remove($this->signalEvents[$signal]);
            unset($this->signalEvents[$signal]);
        }
    }
    public function run()
    {
        $this->running = \true;
        while ($this->running) {
            $this->futureTickQueue->tick();
            $flags = EventLoop::RUN_ONCE;
            if (!$this->running || !$this->futureTickQueue->isEmpty()) {
                $flags |= EventLoop::RUN_NOWAIT;
            } elseif (!$this->readEvents && !$this->writeEvents && !$this->timerEvents->count() && $this->signals->isEmpty()) {
                break;
            }
            $this->loop->run($flags);
        }
    }
    public function stop()
    {
        $this->running = \false;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\EventLoop;

use BadMethodCallException;
use Event;
use EventBase;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Tick\FutureTickQueue;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Timer\Timer;
use SplObjectStorage;
/**
 * [Deprecated] An `ext-libevent` based event loop.
 *
 * This uses the [`libevent` PECL extension](https://pecl.php.net/package/libevent),
 * that provides an interface to `libevent` library.
 * `libevent` itself supports a number of system-specific backends (epoll, kqueue).
 *
 * This event loop does only work with PHP 5.
 * An [unofficial update](https://github.com/php/pecl-event-libevent/pull/2) for
 * PHP 7 does exist, but it is known to cause regular crashes due to `SEGFAULT`s.
 * To reiterate: Using this event loop on PHP 7 is not recommended.
 * Accordingly, neither the [`Loop` class](#loop) nor the deprecated
 * [`Factory` class](#factory) will try to use this event loop on PHP 7.
 *
 * This event loop is known to trigger a readable listener only if
 * the stream *becomes* readable (edge-triggered) and may not trigger if the
 * stream has already been readable from the beginning.
 * This also implies that a stream may not be recognized as readable when data
 * is still left in PHP's internal stream buffers.
 * As such, it's recommended to use `stream_set_read_buffer($stream, 0);`
 * to disable PHP's internal read buffer in this case.
 * See also [`addReadStream()`](#addreadstream) for more details.
 *
 * @link https://pecl.php.net/package/libevent
 * @deprecated 1.2.0, use [`ExtEventLoop`](#exteventloop) instead.
 */
final class ExtLibeventLoop implements LoopInterface
{
    /** @internal */
    const MICROSECONDS_PER_SECOND = 1000000;
    private $eventBase;
    private $futureTickQueue;
    private $timerCallback;
    private $timerEvents;
    private $streamCallback;
    private $readEvents = array();
    private $writeEvents = array();
    private $readListeners = array();
    private $writeListeners = array();
    private $running;
    private $signals;
    private $signalEvents = array();
    public function __construct()
    {
        if (!\function_exists('event_base_new') && !\function_exists('NightwatchAgent_kden27khxA4QoEfj\event_base_new')) {
            throw new BadMethodCallException('Cannot create ExtLibeventLoop, ext-libevent extension missing');
        }
        $this->eventBase = \event_base_new();
        $this->futureTickQueue = new FutureTickQueue();
        $this->timerEvents = new SplObjectStorage();
        $this->signals = new SignalsHandler();
        $this->createTimerCallback();
        $this->createStreamCallback();
    }
    public function addReadStream($stream, $listener)
    {
        $key = (int) $stream;
        if (isset($this->readListeners[$key])) {
            return;
        }
        $event = \event_new();
        \event_set($event, $stream, \EV_PERSIST | \EV_READ, $this->streamCallback);
        \event_base_set($event, $this->eventBase);
        \event_add($event);
        $this->readEvents[$key] = $event;
        $this->readListeners[$key] = $listener;
    }
    public function addWriteStream($stream, $listener)
    {
        $key = (int) $stream;
        if (isset($this->writeListeners[$key])) {
            return;
        }
        $event = \event_new();
        \event_set($event, $stream, \EV_PERSIST | \EV_WRITE, $this->streamCallback);
        \event_base_set($event, $this->eventBase);
        \event_add($event);
        $this->writeEvents[$key] = $event;
        $this->writeListeners[$key] = $listener;
    }
    public function removeReadStream($stream)
    {
        $key = (int) $stream;
        if (isset($this->readListeners[$key])) {
            $event = $this->readEvents[$key];
            \event_del($event);
            \event_free($event);
            unset($this->readEvents[$key], $this->readListeners[$key]);
        }
    }
    public function removeWriteStream($stream)
    {
        $key = (int) $stream;
        if (isset($this->writeListeners[$key])) {
            $event = $this->writeEvents[$key];
            \event_del($event);
            \event_free($event);
            unset($this->writeEvents[$key], $this->writeListeners[$key]);
        }
    }
    public function addTimer($interval, $callback)
    {
        $timer = new Timer($interval, $callback, \false);
        $this->scheduleTimer($timer);
        return $timer;
    }
    public function addPeriodicTimer($interval, $callback)
    {
        $timer = new Timer($interval, $callback, \true);
        $this->scheduleTimer($timer);
        return $timer;
    }
    public function cancelTimer(TimerInterface $timer)
    {
        if ($this->timerEvents->contains($timer)) {
            $event = $this->timerEvents[$timer];
            \event_del($event);
            \event_free($event);
            $this->timerEvents->detach($timer);
        }
    }
    public function futureTick($listener)
    {
        $this->futureTickQueue->add($listener);
    }
    public function addSignal($signal, $listener)
    {
        $this->signals->add($signal, $listener);
        if (!isset($this->signalEvents[$signal])) {
            $this->signalEvents[$signal] = \event_new();
            \event_set($this->signalEvents[$signal], $signal, \EV_PERSIST | \EV_SIGNAL, array($this->signals, 'call'));
            \event_base_set($this->signalEvents[$signal], $this->eventBase);
            \event_add($this->signalEvents[$signal]);
        }
    }
    public function removeSignal($signal, $listener)
    {
        $this->signals->remove($signal, $listener);
        if (isset($this->signalEvents[$signal]) && $this->signals->count($signal) === 0) {
            \event_del($this->signalEvents[$signal]);
            \event_free($this->signalEvents[$signal]);
            unset($this->signalEvents[$signal]);
        }
    }
    public function run()
    {
        $this->running = \true;
        while ($this->running) {
            $this->futureTickQueue->tick();
            $flags = \EVLOOP_ONCE;
            if (!$this->running || !$this->futureTickQueue->isEmpty()) {
                $flags |= \EVLOOP_NONBLOCK;
            } elseif (!$this->readEvents && !$this->writeEvents && !$this->timerEvents->count() && $this->signals->isEmpty()) {
                break;
            }
            \event_base_loop($this->eventBase, $flags);
        }
    }
    public function stop()
    {
        $this->running = \false;
    }
    /**
     * Schedule a timer for execution.
     *
     * @param TimerInterface $timer
     */
    private function scheduleTimer(TimerInterface $timer)
    {
        $this->timerEvents[$timer] = $event = \event_timer_new();
        \event_timer_set($event, $this->timerCallback, $timer);
        \event_base_set($event, $this->eventBase);
        \event_add($event, $timer->getInterval() * self::MICROSECONDS_PER_SECOND);
    }
    /**
     * Create a callback used as the target of timer events.
     *
     * A reference is kept to the callback for the lifetime of the loop
     * to prevent "Cannot destroy active lambda function" fatal error from
     * the event extension.
     */
    private function createTimerCallback()
    {
        $that = $this;
        $timers = $this->timerEvents;
        $this->timerCallback = function ($_, $__, $timer) use ($timers, $that) {
            \call_user_func($timer->getCallback(), $timer);
            // Timer already cancelled ...
            if (!$timers->contains($timer)) {
                return;
            }
            // Reschedule periodic timers ...
            if ($timer->isPeriodic()) {
                \event_add($timers[$timer], $timer->getInterval() * ExtLibeventLoop::MICROSECONDS_PER_SECOND);
                // Clean-up one shot timers ...
            } else {
                $that->cancelTimer($timer);
            }
        };
    }
    /**
     * Create a callback used as the target of stream events.
     *
     * A reference is kept to the callback for the lifetime of the loop
     * to prevent "Cannot destroy active lambda function" fatal error from
     * the event extension.
     */
    private function createStreamCallback()
    {
        $read =& $this->readListeners;
        $write =& $this->writeListeners;
        $this->streamCallback = function ($stream, $flags) use (&$read, &$write) {
            $key = (int) $stream;
            if (\EV_READ === (\EV_READ & $flags) && isset($read[$key])) {
                \call_user_func($read[$key], $stream);
            }
            if (\EV_WRITE === (\EV_WRITE & $flags) && isset($write[$key])) {
                \call_user_func($write[$key], $stream);
            }
        };
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\EventLoop;

use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Tick\FutureTickQueue;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Timer\Timer;
use SplObjectStorage;
/**
 * An `ext-uv` based event loop.
 *
 * This loop uses the [`uv` PECL extension](https://pecl.php.net/package/uv),
 * that provides an interface to `libuv` library.
 * `libuv` itself supports a number of system-specific backends (epoll, kqueue).
 *
 * This loop is known to work with PHP 7+.
 *
 * @see https://github.com/bwoebi/php-uv
 */
final class ExtUvLoop implements LoopInterface
{
    private $uv;
    private $futureTickQueue;
    private $timers;
    private $streamEvents = array();
    private $readStreams = array();
    private $writeStreams = array();
    private $running;
    private $signals;
    private $signalEvents = array();
    private $streamListener;
    public function __construct()
    {
        if (!\function_exists('uv_loop_new') && !\function_exists('NightwatchAgent_kden27khxA4QoEfj\uv_loop_new')) {
            throw new \BadMethodCallException('Cannot create LibUvLoop, ext-uv extension missing');
        }
        $this->uv = \uv_loop_new();
        $this->futureTickQueue = new FutureTickQueue();
        $this->timers = new SplObjectStorage();
        $this->streamListener = $this->createStreamListener();
        $this->signals = new SignalsHandler();
    }
    /**
     * Returns the underlying ext-uv event loop. (Internal ReactPHP use only.)
     *
     * @internal
     *
     * @return resource
     */
    public function getUvLoop()
    {
        return $this->uv;
    }
    /**
     * {@inheritdoc}
     */
    public function addReadStream($stream, $listener)
    {
        if (isset($this->readStreams[(int) $stream])) {
            return;
        }
        $this->readStreams[(int) $stream] = $listener;
        $this->addStream($stream);
    }
    /**
     * {@inheritdoc}
     */
    public function addWriteStream($stream, $listener)
    {
        if (isset($this->writeStreams[(int) $stream])) {
            return;
        }
        $this->writeStreams[(int) $stream] = $listener;
        $this->addStream($stream);
    }
    /**
     * {@inheritdoc}
     */
    public function removeReadStream($stream)
    {
        if (!isset($this->streamEvents[(int) $stream])) {
            return;
        }
        unset($this->readStreams[(int) $stream]);
        $this->removeStream($stream);
    }
    /**
     * {@inheritdoc}
     */
    public function removeWriteStream($stream)
    {
        if (!isset($this->streamEvents[(int) $stream])) {
            return;
        }
        unset($this->writeStreams[(int) $stream]);
        $this->removeStream($stream);
    }
    /**
     * {@inheritdoc}
     */
    public function addTimer($interval, $callback)
    {
        $timer = new Timer($interval, $callback, \false);
        $that = $this;
        $timers = $this->timers;
        $callback = function () use ($timer, $timers, $that) {
            \call_user_func($timer->getCallback(), $timer);
            if ($timers->offsetExists($timer)) {
                $that->cancelTimer($timer);
            }
        };
        $event = \uv_timer_init($this->uv);
        $this->timers->offsetSet($timer, $event);
        \uv_timer_start($event, $this->convertFloatSecondsToMilliseconds($interval), 0, $callback);
        return $timer;
    }
    /**
     * {@inheritdoc}
     */
    public function addPeriodicTimer($interval, $callback)
    {
        $timer = new Timer($interval, $callback, \true);
        $callback = function () use ($timer) {
            \call_user_func($timer->getCallback(), $timer);
        };
        $interval = $this->convertFloatSecondsToMilliseconds($interval);
        $event = \uv_timer_init($this->uv);
        $this->timers->offsetSet($timer, $event);
        \uv_timer_start($event, $interval, (int) $interval === 0 ? 1 : $interval, $callback);
        return $timer;
    }
    /**
     * {@inheritdoc}
     */
    public function cancelTimer(TimerInterface $timer)
    {
        if (isset($this->timers[$timer])) {
            @\uv_timer_stop($this->timers[$timer]);
            $this->timers->offsetUnset($timer);
        }
    }
    /**
     * {@inheritdoc}
     */
    public function futureTick($listener)
    {
        $this->futureTickQueue->add($listener);
    }
    public function addSignal($signal, $listener)
    {
        $this->signals->add($signal, $listener);
        if (!isset($this->signalEvents[$signal])) {
            $signals = $this->signals;
            $this->signalEvents[$signal] = \uv_signal_init($this->uv);
            \uv_signal_start($this->signalEvents[$signal], function () use ($signals, $signal) {
                $signals->call($signal);
            }, $signal);
        }
    }
    public function removeSignal($signal, $listener)
    {
        $this->signals->remove($signal, $listener);
        if (isset($this->signalEvents[$signal]) && $this->signals->count($signal) === 0) {
            \uv_signal_stop($this->signalEvents[$signal]);
            unset($this->signalEvents[$signal]);
        }
    }
    /**
     * {@inheritdoc}
     */
    public function run()
    {
        $this->running = \true;
        while ($this->running) {
            $this->futureTickQueue->tick();
            $hasPendingCallbacks = !$this->futureTickQueue->isEmpty();
            $wasJustStopped = !$this->running;
            $nothingLeftToDo = !$this->readStreams && !$this->writeStreams && !$this->timers->count() && $this->signals->isEmpty();
            // Use UV::RUN_ONCE when there are only I/O events active in the loop and block until one of those triggers,
            // otherwise use UV::RUN_NOWAIT.
            // @link http://docs.libuv.org/en/v1.x/loop.html#c.uv_run
            $flags = \UV::RUN_ONCE;
            if ($wasJustStopped || $hasPendingCallbacks) {
                $flags = \UV::RUN_NOWAIT;
            } elseif ($nothingLeftToDo) {
                break;
            }
            \uv_run($this->uv, $flags);
        }
    }
    /**
     * {@inheritdoc}
     */
    public function stop()
    {
        $this->running = \false;
    }
    private function addStream($stream)
    {
        if (!isset($this->streamEvents[(int) $stream])) {
            $this->streamEvents[(int) $stream] = \NightwatchAgent_kden27khxA4QoEfj\uv_poll_init_socket($this->uv, $stream);
        }
        if ($this->streamEvents[(int) $stream] !== \false) {
            $this->pollStream($stream);
        }
    }
    private function removeStream($stream)
    {
        if (!isset($this->streamEvents[(int) $stream])) {
            return;
        }
        if (!isset($this->readStreams[(int) $stream]) && !isset($this->writeStreams[(int) $stream])) {
            \uv_poll_stop($this->streamEvents[(int) $stream]);
            \uv_close($this->streamEvents[(int) $stream]);
            unset($this->streamEvents[(int) $stream]);
            return;
        }
        $this->pollStream($stream);
    }
    private function pollStream($stream)
    {
        if (!isset($this->streamEvents[(int) $stream])) {
            return;
        }
        $flags = 0;
        if (isset($this->readStreams[(int) $stream])) {
            $flags |= \UV::READABLE;
        }
        if (isset($this->writeStreams[(int) $stream])) {
            $flags |= \UV::WRITABLE;
        }
        \uv_poll_start($this->streamEvents[(int) $stream], $flags, $this->streamListener);
    }
    /**
     * Create a stream listener
     *
     * @return callable Returns a callback
     */
    private function createStreamListener()
    {
        $callback = function ($event, $status, $events, $stream) {
            // libuv automatically stops polling on error, re-enable polling to match other loop implementations
            if ($status !== 0) {
                $this->pollStream($stream);
                // libuv may report no events on error, but this should still invoke stream listeners to report closed connections
                // re-enable both readable and writable, correct listeners will be checked below anyway
                if ($events === 0) {
                    $events = \UV::READABLE | \UV::WRITABLE;
                }
            }
            if (isset($this->readStreams[(int) $stream]) && $events & \UV::READABLE) {
                \call_user_func($this->readStreams[(int) $stream], $stream);
            }
            if (isset($this->writeStreams[(int) $stream]) && $events & \UV::WRITABLE) {
                \call_user_func($this->writeStreams[(int) $stream], $stream);
            }
        };
        return $callback;
    }
    /**
     * @param float $interval
     * @return int
     */
    private function convertFloatSecondsToMilliseconds($interval)
    {
        if ($interval < 0) {
            return 0;
        }
        $maxValue = (int) (\PHP_INT_MAX / 1000);
        $intervalOverflow = \false;
        if (\PHP_VERSION_ID > 80499 && $interval >= \PHP_INT_MAX + 1) {
            $intervalOverflow = \true;
        } else {
            $intInterval = (int) $interval;
            if ($intInterval <= 0 && $interval > 1 || $intInterval >= $maxValue) {
                $intervalOverflow = \true;
            }
        }
        if ($intervalOverflow) {
            throw new \InvalidArgumentException("Interval overflow, value must be lower than '{$maxValue}', but '{$interval}' passed.");
        }
        return (int) \floor($interval * 1000);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\EventLoop;

/**
 * [Deprecated] The `Factory` class exists as a convenient way to pick the best available event loop implementation.
 *
 * @deprecated 1.2.0 See Loop instead.
 * @see Loop
 */
final class Factory
{
    /**
     * [Deprecated] Creates a new event loop instance
     *
     * ```php
     * // deprecated
     * $loop = React\EventLoop\Factory::create();
     *
     * // new
     * $loop = React\EventLoop\Loop::get();
     * ```
     *
     * This method always returns an instance implementing `LoopInterface`,
     * the actual event loop implementation is an implementation detail.
     *
     * This method should usually only be called once at the beginning of the program.
     *
     * @deprecated 1.2.0 See Loop::get() instead.
     * @see Loop::get()
     *
     * @return LoopInterface
     */
    public static function create()
    {
        $loop = self::construct();
        Loop::set($loop);
        return $loop;
    }
    /**
     * @internal
     * @return LoopInterface
     */
    private static function construct()
    {
        // @codeCoverageIgnoreStart
        if (\function_exists('uv_loop_new')) {
            // only use ext-uv on PHP 7
            return new ExtUvLoop();
        }
        if (\class_exists('NightwatchAgent_kden27khxA4QoEfj\libev\EventLoop', \false)) {
            return new ExtLibevLoop();
        }
        if (\class_exists('EvLoop', \false)) {
            return new ExtEvLoop();
        }
        if (\class_exists('EventBase', \false)) {
            return new ExtEventLoop();
        }
        if (\function_exists('event_base_new') && \PHP_MAJOR_VERSION === 5) {
            // only use ext-libevent on PHP 5 for now
            return new ExtLibeventLoop();
        }
        return new StreamSelectLoop();
        // @codeCoverageIgnoreEnd
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\EventLoop;

/**
 * The `Loop` class exists as a convenient way to get the currently relevant loop
 */
final class Loop
{
    /**
     * @var ?LoopInterface
     */
    private static $instance;
    /** @var bool */
    private static $stopped = \false;
    /**
     * Returns the event loop.
     * When no loop is set, it will call the factory to create one.
     *
     * This method always returns an instance implementing `LoopInterface`,
     * the actual event loop implementation is an implementation detail.
     *
     * This method is the preferred way to get the event loop and using
     * Factory::create has been deprecated.
     *
     * @return LoopInterface
     */
    public static function get()
    {
        if (self::$instance instanceof LoopInterface) {
            return self::$instance;
        }
        self::$instance = $loop = Factory::create();
        // Automatically run loop at end of program, unless already started or stopped explicitly.
        // This is tested using child processes, so coverage is actually 100%, see BinTest.
        // @codeCoverageIgnoreStart
        $hasRun = \false;
        $loop->futureTick(function () use (&$hasRun) {
            $hasRun = \true;
        });
        $stopped =& self::$stopped;
        register_shutdown_function(function () use ($loop, &$hasRun, &$stopped) {
            // Don't run if we're coming from a fatal error (uncaught exception).
            $error = error_get_last();
            if ((isset($error['type']) ? $error['type'] : 0) & (\E_ERROR | \E_CORE_ERROR | \E_COMPILE_ERROR | \E_USER_ERROR | \E_RECOVERABLE_ERROR)) {
                return;
            }
            if (!$hasRun && !$stopped) {
                $loop->run();
            }
        });
        // @codeCoverageIgnoreEnd
        return self::$instance;
    }
    /**
     * Internal undocumented method, behavior might change or throw in the
     * future. Use with caution and at your own risk.
     *
     * @internal
     * @return void
     */
    public static function set(LoopInterface $loop)
    {
        self::$instance = $loop;
    }
    /**
     * [Advanced] Register a listener to be notified when a stream is ready to read.
     *
     * @param resource $stream
     * @param callable $listener
     * @return void
     * @throws \Exception
     * @see LoopInterface::addReadStream()
     */
    public static function addReadStream($stream, $listener)
    {
        // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls)
        if (self::$instance === null) {
            self::get();
        }
        self::$instance->addReadStream($stream, $listener);
    }
    /**
     * [Advanced] Register a listener to be notified when a stream is ready to write.
     *
     * @param resource $stream
     * @param callable $listener
     * @return void
     * @throws \Exception
     * @see LoopInterface::addWriteStream()
     */
    public static function addWriteStream($stream, $listener)
    {
        // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls)
        if (self::$instance === null) {
            self::get();
        }
        self::$instance->addWriteStream($stream, $listener);
    }
    /**
     * Remove the read event listener for the given stream.
     *
     * @param resource $stream
     * @return void
     * @see LoopInterface::removeReadStream()
     */
    public static function removeReadStream($stream)
    {
        if (self::$instance !== null) {
            self::$instance->removeReadStream($stream);
        }
    }
    /**
     * Remove the write event listener for the given stream.
     *
     * @param resource $stream
     * @return void
     * @see LoopInterface::removeWriteStream()
     */
    public static function removeWriteStream($stream)
    {
        if (self::$instance !== null) {
            self::$instance->removeWriteStream($stream);
        }
    }
    /**
     * Enqueue a callback to be invoked once after the given interval.
     *
     * @param float $interval
     * @param callable $callback
     * @return TimerInterface
     * @see LoopInterface::addTimer()
     */
    public static function addTimer($interval, $callback)
    {
        // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls)
        if (self::$instance === null) {
            self::get();
        }
        return self::$instance->addTimer($interval, $callback);
    }
    /**
     * Enqueue a callback to be invoked repeatedly after the given interval.
     *
     * @param float $interval
     * @param callable $callback
     * @return TimerInterface
     * @see LoopInterface::addPeriodicTimer()
     */
    public static function addPeriodicTimer($interval, $callback)
    {
        // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls)
        if (self::$instance === null) {
            self::get();
        }
        return self::$instance->addPeriodicTimer($interval, $callback);
    }
    /**
     * Cancel a pending timer.
     *
     * @param TimerInterface $timer
     * @return void
     * @see LoopInterface::cancelTimer()
     */
    public static function cancelTimer(TimerInterface $timer)
    {
        if (self::$instance !== null) {
            self::$instance->cancelTimer($timer);
        }
    }
    /**
     * Schedule a callback to be invoked on a future tick of the event loop.
     *
     * @param callable $listener
     * @return void
     * @see LoopInterface::futureTick()
     */
    public static function futureTick($listener)
    {
        // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls)
        if (self::$instance === null) {
            self::get();
        }
        self::$instance->futureTick($listener);
    }
    /**
     * Register a listener to be notified when a signal has been caught by this process.
     *
     * @param int $signal
     * @param callable $listener
     * @return void
     * @see LoopInterface::addSignal()
     */
    public static function addSignal($signal, $listener)
    {
        // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls)
        if (self::$instance === null) {
            self::get();
        }
        self::$instance->addSignal($signal, $listener);
    }
    /**
     * Removes a previously added signal listener.
     *
     * @param int $signal
     * @param callable $listener
     * @return void
     * @see LoopInterface::removeSignal()
     */
    public static function removeSignal($signal, $listener)
    {
        if (self::$instance !== null) {
            self::$instance->removeSignal($signal, $listener);
        }
    }
    /**
     * Run the event loop until there are no more tasks to perform.
     *
     * @return void
     * @see LoopInterface::run()
     */
    public static function run()
    {
        // create loop instance on demand (legacy PHP < 7 doesn't like ternaries in method calls)
        if (self::$instance === null) {
            self::get();
        }
        self::$instance->run();
    }
    /**
     * Instruct a running event loop to stop.
     *
     * @return void
     * @see LoopInterface::stop()
     */
    public static function stop()
    {
        self::$stopped = \true;
        if (self::$instance !== null) {
            self::$instance->stop();
        }
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\EventLoop;

interface LoopInterface
{
    /**
     * [Advanced] Register a listener to be notified when a stream is ready to read.
     *
     * Note that this low-level API is considered advanced usage.
     * Most use cases should probably use the higher-level
     * [readable Stream API](https://github.com/reactphp/stream#readablestreaminterface)
     * instead.
     *
     * The first parameter MUST be a valid stream resource that supports
     * checking whether it is ready to read by this loop implementation.
     * A single stream resource MUST NOT be added more than once.
     * Instead, either call [`removeReadStream()`](#removereadstream) first or
     * react to this event with a single listener and then dispatch from this
     * listener. This method MAY throw an `Exception` if the given resource type
     * is not supported by this loop implementation.
     *
     * The second parameter MUST be a listener callback function that accepts
     * the stream resource as its only parameter.
     * If you don't use the stream resource inside your listener callback function
     * you MAY use a function which has no parameters at all.
     *
     * The listener callback function MUST NOT throw an `Exception`.
     * The return value of the listener callback function will be ignored and has
     * no effect, so for performance reasons you're recommended to not return
     * any excessive data structures.
     *
     * If you want to access any variables within your callback function, you
     * can bind arbitrary data to a callback closure like this:
     *
     * ```php
     * $loop->addReadStream($stream, function ($stream) use ($name) {
     *     echo $name . ' said: ' . fread($stream);
     * });
     * ```
     *
     * See also [example #11](examples).
     *
     * You can invoke [`removeReadStream()`](#removereadstream) to remove the
     * read event listener for this stream.
     *
     * The execution order of listeners when multiple streams become ready at
     * the same time is not guaranteed.
     *
     * @param resource $stream   The PHP stream resource to check.
     * @param callable $listener Invoked when the stream is ready.
     * @throws \Exception if the given resource type is not supported by this loop implementation
     * @see self::removeReadStream()
     */
    public function addReadStream($stream, $listener);
    /**
     * [Advanced] Register a listener to be notified when a stream is ready to write.
     *
     * Note that this low-level API is considered advanced usage.
     * Most use cases should probably use the higher-level
     * [writable Stream API](https://github.com/reactphp/stream#writablestreaminterface)
     * instead.
     *
     * The first parameter MUST be a valid stream resource that supports
     * checking whether it is ready to write by this loop implementation.
     * A single stream resource MUST NOT be added more than once.
     * Instead, either call [`removeWriteStream()`](#removewritestream) first or
     * react to this event with a single listener and then dispatch from this
     * listener. This method MAY throw an `Exception` if the given resource type
     * is not supported by this loop implementation.
     *
     * The second parameter MUST be a listener callback function that accepts
     * the stream resource as its only parameter.
     * If you don't use the stream resource inside your listener callback function
     * you MAY use a function which has no parameters at all.
     *
     * The listener callback function MUST NOT throw an `Exception`.
     * The return value of the listener callback function will be ignored and has
     * no effect, so for performance reasons you're recommended to not return
     * any excessive data structures.
     *
     * If you want to access any variables within your callback function, you
     * can bind arbitrary data to a callback closure like this:
     *
     * ```php
     * $loop->addWriteStream($stream, function ($stream) use ($name) {
     *     fwrite($stream, 'Hello ' . $name);
     * });
     * ```
     *
     * See also [example #12](examples).
     *
     * You can invoke [`removeWriteStream()`](#removewritestream) to remove the
     * write event listener for this stream.
     *
     * The execution order of listeners when multiple streams become ready at
     * the same time is not guaranteed.
     *
     * Some event loop implementations are known to only trigger the listener if
     * the stream *becomes* readable (edge-triggered) and may not trigger if the
     * stream has already been readable from the beginning.
     * This also implies that a stream may not be recognized as readable when data
     * is still left in PHP's internal stream buffers.
     * As such, it's recommended to use `stream_set_read_buffer($stream, 0);`
     * to disable PHP's internal read buffer in this case.
     *
     * @param resource $stream   The PHP stream resource to check.
     * @param callable $listener Invoked when the stream is ready.
     * @throws \Exception if the given resource type is not supported by this loop implementation
     * @see self::removeWriteStream()
     */
    public function addWriteStream($stream, $listener);
    /**
     * Remove the read event listener for the given stream.
     *
     * Removing a stream from the loop that has already been removed or trying
     * to remove a stream that was never added or is invalid has no effect.
     *
     * @param resource $stream The PHP stream resource.
     */
    public function removeReadStream($stream);
    /**
     * Remove the write event listener for the given stream.
     *
     * Removing a stream from the loop that has already been removed or trying
     * to remove a stream that was never added or is invalid has no effect.
     *
     * @param resource $stream The PHP stream resource.
     */
    public function removeWriteStream($stream);
    /**
     * Enqueue a callback to be invoked once after the given interval.
     *
     * The second parameter MUST be a timer callback function that accepts
     * the timer instance as its only parameter.
     * If you don't use the timer instance inside your timer callback function
     * you MAY use a function which has no parameters at all.
     *
     * The timer callback function MUST NOT throw an `Exception`.
     * The return value of the timer callback function will be ignored and has
     * no effect, so for performance reasons you're recommended to not return
     * any excessive data structures.
     *
     * This method returns a timer instance. The same timer instance will also be
     * passed into the timer callback function as described above.
     * You can invoke [`cancelTimer`](#canceltimer) to cancel a pending timer.
     * Unlike [`addPeriodicTimer()`](#addperiodictimer), this method will ensure
     * the callback will be invoked only once after the given interval.
     *
     * ```php
     * $loop->addTimer(0.8, function () {
     *     echo 'world!' . PHP_EOL;
     * });
     *
     * $loop->addTimer(0.3, function () {
     *     echo 'hello ';
     * });
     * ```
     *
     * See also [example #1](examples).
     *
     * If you want to access any variables within your callback function, you
     * can bind arbitrary data to a callback closure like this:
     *
     * ```php
     * function hello($name, LoopInterface $loop)
     * {
     *     $loop->addTimer(1.0, function () use ($name) {
     *         echo "hello $name\n";
     *     });
     * }
     *
     * hello('Tester', $loop);
     * ```
     *
     * This interface does not enforce any particular timer resolution, so
     * special care may have to be taken if you rely on very high precision with
     * millisecond accuracy or below. Event loop implementations SHOULD work on
     * a best effort basis and SHOULD provide at least millisecond accuracy
     * unless otherwise noted. Many existing event loop implementations are
     * known to provide microsecond accuracy, but it's generally not recommended
     * to rely on this high precision.
     *
     * Similarly, the execution order of timers scheduled to execute at the
     * same time (within its possible accuracy) is not guaranteed.
     *
     * This interface suggests that event loop implementations SHOULD use a
     * monotonic time source if available. Given that a monotonic time source is
     * only available as of PHP 7.3 by default, event loop implementations MAY
     * fall back to using wall-clock time.
     * While this does not affect many common use cases, this is an important
     * distinction for programs that rely on a high time precision or on systems
     * that are subject to discontinuous time adjustments (time jumps).
     * This means that if you schedule a timer to trigger in 30s and then adjust
     * your system time forward by 20s, the timer SHOULD still trigger in 30s.
     * See also [event loop implementations](#loop-implementations) for more details.
     *
     * @param int|float $interval The number of seconds to wait before execution.
     * @param callable  $callback The callback to invoke.
     *
     * @return TimerInterface
     */
    public function addTimer($interval, $callback);
    /**
     * Enqueue a callback to be invoked repeatedly after the given interval.
     *
     * The second parameter MUST be a timer callback function that accepts
     * the timer instance as its only parameter.
     * If you don't use the timer instance inside your timer callback function
     * you MAY use a function which has no parameters at all.
     *
     * The timer callback function MUST NOT throw an `Exception`.
     * The return value of the timer callback function will be ignored and has
     * no effect, so for performance reasons you're recommended to not return
     * any excessive data structures.
     *
     * This method returns a timer instance. The same timer instance will also be
     * passed into the timer callback function as described above.
     * Unlike [`addTimer()`](#addtimer), this method will ensure the callback
     * will be invoked infinitely after the given interval or until you invoke
     * [`cancelTimer`](#canceltimer).
     *
     * ```php
     * $timer = $loop->addPeriodicTimer(0.1, function () {
     *     echo 'tick!' . PHP_EOL;
     * });
     *
     * $loop->addTimer(1.0, function () use ($loop, $timer) {
     *     $loop->cancelTimer($timer);
     *     echo 'Done' . PHP_EOL;
     * });
     * ```
     *
     * See also [example #2](examples).
     *
     * If you want to limit the number of executions, you can bind
     * arbitrary data to a callback closure like this:
     *
     * ```php
     * function hello($name, LoopInterface $loop)
     * {
     *     $n = 3;
     *     $loop->addPeriodicTimer(1.0, function ($timer) use ($name, $loop, &$n) {
     *         if ($n > 0) {
     *             --$n;
     *             echo "hello $name\n";
     *         } else {
     *             $loop->cancelTimer($timer);
     *         }
     *     });
     * }
     *
     * hello('Tester', $loop);
     * ```
     *
     * This interface does not enforce any particular timer resolution, so
     * special care may have to be taken if you rely on very high precision with
     * millisecond accuracy or below. Event loop implementations SHOULD work on
     * a best effort basis and SHOULD provide at least millisecond accuracy
     * unless otherwise noted. Many existing event loop implementations are
     * known to provide microsecond accuracy, but it's generally not recommended
     * to rely on this high precision.
     *
     * Similarly, the execution order of timers scheduled to execute at the
     * same time (within its possible accuracy) is not guaranteed.
     *
     * This interface suggests that event loop implementations SHOULD use a
     * monotonic time source if available. Given that a monotonic time source is
     * only available as of PHP 7.3 by default, event loop implementations MAY
     * fall back to using wall-clock time.
     * While this does not affect many common use cases, this is an important
     * distinction for programs that rely on a high time precision or on systems
     * that are subject to discontinuous time adjustments (time jumps).
     * This means that if you schedule a timer to trigger in 30s and then adjust
     * your system time forward by 20s, the timer SHOULD still trigger in 30s.
     * See also [event loop implementations](#loop-implementations) for more details.
     *
     * Additionally, periodic timers may be subject to timer drift due to
     * re-scheduling after each invocation. As such, it's generally not
     * recommended to rely on this for high precision intervals with millisecond
     * accuracy or below.
     *
     * @param int|float $interval The number of seconds to wait before execution.
     * @param callable  $callback The callback to invoke.
     *
     * @return TimerInterface
     */
    public function addPeriodicTimer($interval, $callback);
    /**
     * Cancel a pending timer.
     *
     * See also [`addPeriodicTimer()`](#addperiodictimer) and [example #2](examples).
     *
     * Calling this method on a timer instance that has not been added to this
     * loop instance or on a timer that has already been cancelled has no effect.
     *
     * @param TimerInterface $timer The timer to cancel.
     *
     * @return void
     */
    public function cancelTimer(TimerInterface $timer);
    /**
     * Schedule a callback to be invoked on a future tick of the event loop.
     *
     * This works very much similar to timers with an interval of zero seconds,
     * but does not require the overhead of scheduling a timer queue.
     *
     * The tick callback function MUST be able to accept zero parameters.
     *
     * The tick callback function MUST NOT throw an `Exception`.
     * The return value of the tick callback function will be ignored and has
     * no effect, so for performance reasons you're recommended to not return
     * any excessive data structures.
     *
     * If you want to access any variables within your callback function, you
     * can bind arbitrary data to a callback closure like this:
     *
     * ```php
     * function hello($name, LoopInterface $loop)
     * {
     *     $loop->futureTick(function () use ($name) {
     *         echo "hello $name\n";
     *     });
     * }
     *
     * hello('Tester', $loop);
     * ```
     *
     * Unlike timers, tick callbacks are guaranteed to be executed in the order
     * they are enqueued.
     * Also, once a callback is enqueued, there's no way to cancel this operation.
     *
     * This is often used to break down bigger tasks into smaller steps (a form
     * of cooperative multitasking).
     *
     * ```php
     * $loop->futureTick(function () {
     *     echo 'b';
     * });
     * $loop->futureTick(function () {
     *     echo 'c';
     * });
     * echo 'a';
     * ```
     *
     * See also [example #3](examples).
     *
     * @param callable $listener The callback to invoke.
     *
     * @return void
     */
    public function futureTick($listener);
    /**
     * Register a listener to be notified when a signal has been caught by this process.
     *
     * This is useful to catch user interrupt signals or shutdown signals from
     * tools like `supervisor` or `systemd`.
     *
     * The second parameter MUST be a listener callback function that accepts
     * the signal as its only parameter.
     * If you don't use the signal inside your listener callback function
     * you MAY use a function which has no parameters at all.
     *
     * The listener callback function MUST NOT throw an `Exception`.
     * The return value of the listener callback function will be ignored and has
     * no effect, so for performance reasons you're recommended to not return
     * any excessive data structures.
     *
     * ```php
     * $loop->addSignal(SIGINT, function (int $signal) {
     *     echo 'Caught user interrupt signal' . PHP_EOL;
     * });
     * ```
     *
     * See also [example #4](examples).
     *
     * Signaling is only available on Unix-like platforms, Windows isn't
     * supported due to operating system limitations.
     * This method may throw a `BadMethodCallException` if signals aren't
     * supported on this platform, for example when required extensions are
     * missing.
     *
     * **Note: A listener can only be added once to the same signal, any
     * attempts to add it more than once will be ignored.**
     *
     * @param int $signal
     * @param callable $listener
     *
     * @throws \BadMethodCallException when signals aren't supported on this
     *     platform, for example when required extensions are missing.
     *
     * @return void
     */
    public function addSignal($signal, $listener);
    /**
     * Removes a previously added signal listener.
     *
     * ```php
     * $loop->removeSignal(SIGINT, $listener);
     * ```
     *
     * Any attempts to remove listeners that aren't registered will be ignored.
     *
     * @param int $signal
     * @param callable $listener
     *
     * @return void
     */
    public function removeSignal($signal, $listener);
    /**
     * Run the event loop until there are no more tasks to perform.
     *
     * For many applications, this method is the only directly visible
     * invocation on the event loop.
     * As a rule of thumb, it is usually recommended to attach everything to the
     * same loop instance and then run the loop once at the bottom end of the
     * application.
     *
     * ```php
     * $loop->run();
     * ```
     *
     * This method will keep the loop running until there are no more tasks
     * to perform. In other words: This method will block until the last
     * timer, stream and/or signal has been removed.
     *
     * Likewise, it is imperative to ensure the application actually invokes
     * this method once. Adding listeners to the loop and missing to actually
     * run it will result in the application exiting without actually waiting
     * for any of the attached listeners.
     *
     * This method MUST NOT be called while the loop is already running.
     * This method MAY be called more than once after it has explicitly been
     * [`stop()`ped](#stop) or after it automatically stopped because it
     * previously did no longer have anything to do.
     *
     * @return void
     */
    public function run();
    /**
     * Instruct a running event loop to stop.
     *
     * This method is considered advanced usage and should be used with care.
     * As a rule of thumb, it is usually recommended to let the loop stop
     * only automatically when it no longer has anything to do.
     *
     * This method can be used to explicitly instruct the event loop to stop:
     *
     * ```php
     * $loop->addTimer(3.0, function () use ($loop) {
     *     $loop->stop();
     * });
     * ```
     *
     * Calling this method on a loop instance that is not currently running or
     * on a loop instance that has already been stopped has no effect.
     *
     * @return void
     */
    public function stop();
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\EventLoop;

/**
 * @internal
 */
final class SignalsHandler
{
    private $signals = array();
    public function add($signal, $listener)
    {
        if (!isset($this->signals[$signal])) {
            $this->signals[$signal] = array();
        }
        if (\in_array($listener, $this->signals[$signal])) {
            return;
        }
        $this->signals[$signal][] = $listener;
    }
    public function remove($signal, $listener)
    {
        if (!isset($this->signals[$signal])) {
            return;
        }
        $index = \array_search($listener, $this->signals[$signal], \true);
        unset($this->signals[$signal][$index]);
        if (isset($this->signals[$signal]) && \count($this->signals[$signal]) === 0) {
            unset($this->signals[$signal]);
        }
    }
    public function call($signal)
    {
        if (!isset($this->signals[$signal])) {
            return;
        }
        foreach ($this->signals[$signal] as $listener) {
            \call_user_func($listener, $signal);
        }
    }
    public function count($signal)
    {
        if (!isset($this->signals[$signal])) {
            return 0;
        }
        return \count($this->signals[$signal]);
    }
    public function isEmpty()
    {
        return !$this->signals;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\EventLoop;

use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Tick\FutureTickQueue;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Timer\Timer;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Timer\Timers;
/**
 * A `stream_select()` based event loop.
 *
 * This uses the [`stream_select()`](https://www.php.net/manual/en/function.stream-select.php)
 * function and is the only implementation that works out of the box with PHP.
 *
 * This event loop works out of the box on PHP 5.4 through PHP 8+ and HHVM.
 * This means that no installation is required and this library works on all
 * platforms and supported PHP versions.
 * Accordingly, the [`Loop` class](#loop) and the deprecated [`Factory`](#factory)
 * will use this event loop by default if you do not install any of the event loop
 * extensions listed below.
 *
 * Under the hood, it does a simple `select` system call.
 * This system call is limited to the maximum file descriptor number of
 * `FD_SETSIZE` (platform dependent, commonly 1024) and scales with `O(m)`
 * (`m` being the maximum file descriptor number passed).
 * This means that you may run into issues when handling thousands of streams
 * concurrently and you may want to look into using one of the alternative
 * event loop implementations listed below in this case.
 * If your use case is among the many common use cases that involve handling only
 * dozens or a few hundred streams at once, then this event loop implementation
 * performs really well.
 *
 * If you want to use signal handling (see also [`addSignal()`](#addsignal) below),
 * this event loop implementation requires `ext-pcntl`.
 * This extension is only available for Unix-like platforms and does not support
 * Windows.
 * It is commonly installed as part of many PHP distributions.
 * If this extension is missing (or you're running on Windows), signal handling is
 * not supported and throws a `BadMethodCallException` instead.
 *
 * This event loop is known to rely on wall-clock time to schedule future timers
 * when using any version before PHP 7.3, because a monotonic time source is
 * only available as of PHP 7.3 (`hrtime()`).
 * While this does not affect many common use cases, this is an important
 * distinction for programs that rely on a high time precision or on systems
 * that are subject to discontinuous time adjustments (time jumps).
 * This means that if you schedule a timer to trigger in 30s on PHP < 7.3 and
 * then adjust your system time forward by 20s, the timer may trigger in 10s.
 * See also [`addTimer()`](#addtimer) for more details.
 *
 * @link https://www.php.net/manual/en/function.stream-select.php
 */
final class StreamSelectLoop implements LoopInterface
{
    /** @internal */
    const MICROSECONDS_PER_SECOND = 1000000;
    private $futureTickQueue;
    private $timers;
    private $readStreams = array();
    private $readListeners = array();
    private $writeStreams = array();
    private $writeListeners = array();
    private $running;
    private $pcntl = \false;
    private $pcntlPoll = \false;
    private $signals;
    public function __construct()
    {
        $this->futureTickQueue = new FutureTickQueue();
        $this->timers = new Timers();
        $this->pcntl = \function_exists('pcntl_signal') && \function_exists('pcntl_signal_dispatch');
        $this->pcntlPoll = $this->pcntl && !\function_exists('pcntl_async_signals');
        $this->signals = new SignalsHandler();
        // prefer async signals if available (PHP 7.1+) or fall back to dispatching on each tick
        if ($this->pcntl && !$this->pcntlPoll) {
            \pcntl_async_signals(\true);
        }
    }
    public function addReadStream($stream, $listener)
    {
        $key = (int) $stream;
        if (!isset($this->readStreams[$key])) {
            $this->readStreams[$key] = $stream;
            $this->readListeners[$key] = $listener;
        }
    }
    public function addWriteStream($stream, $listener)
    {
        $key = (int) $stream;
        if (!isset($this->writeStreams[$key])) {
            $this->writeStreams[$key] = $stream;
            $this->writeListeners[$key] = $listener;
        }
    }
    public function removeReadStream($stream)
    {
        $key = (int) $stream;
        unset($this->readStreams[$key], $this->readListeners[$key]);
    }
    public function removeWriteStream($stream)
    {
        $key = (int) $stream;
        unset($this->writeStreams[$key], $this->writeListeners[$key]);
    }
    public function addTimer($interval, $callback)
    {
        $timer = new Timer($interval, $callback, \false);
        $this->timers->add($timer);
        return $timer;
    }
    public function addPeriodicTimer($interval, $callback)
    {
        $timer = new Timer($interval, $callback, \true);
        $this->timers->add($timer);
        return $timer;
    }
    public function cancelTimer(TimerInterface $timer)
    {
        $this->timers->cancel($timer);
    }
    public function futureTick($listener)
    {
        $this->futureTickQueue->add($listener);
    }
    public function addSignal($signal, $listener)
    {
        if ($this->pcntl === \false) {
            throw new \BadMethodCallException('Event loop feature "signals" isn\'t supported by the "StreamSelectLoop"');
        }
        $first = $this->signals->count($signal) === 0;
        $this->signals->add($signal, $listener);
        if ($first) {
            \pcntl_signal($signal, array($this->signals, 'call'));
        }
    }
    public function removeSignal($signal, $listener)
    {
        if (!$this->signals->count($signal)) {
            return;
        }
        $this->signals->remove($signal, $listener);
        if ($this->signals->count($signal) === 0) {
            \pcntl_signal($signal, \SIG_DFL);
        }
    }
    public function run()
    {
        $this->running = \true;
        while ($this->running) {
            $this->futureTickQueue->tick();
            $this->timers->tick();
            // Future-tick queue has pending callbacks ...
            if (!$this->running || !$this->futureTickQueue->isEmpty()) {
                $timeout = 0;
                // There is a pending timer, only block until it is due ...
            } elseif ($scheduledAt = $this->timers->getFirst()) {
                $timeout = $scheduledAt - $this->timers->getTime();
                if ($timeout < 0) {
                    $timeout = 0;
                } else {
                    // Convert float seconds to int microseconds.
                    // Ensure we do not exceed maximum integer size, which may
                    // cause the loop to tick once every ~35min on 32bit systems.
                    $timeout *= self::MICROSECONDS_PER_SECOND;
                    $timeout = $timeout > \PHP_INT_MAX ? \PHP_INT_MAX : (int) $timeout;
                }
                // The only possible event is stream or signal activity, so wait forever ...
            } elseif ($this->readStreams || $this->writeStreams || !$this->signals->isEmpty()) {
                $timeout = null;
                // There's nothing left to do ...
            } else {
                break;
            }
            $this->waitForStreamActivity($timeout);
        }
    }
    public function stop()
    {
        $this->running = \false;
    }
    /**
     * Wait/check for stream activity, or until the next timer is due.
     *
     * @param integer|null $timeout Activity timeout in microseconds, or null to wait forever.
     */
    private function waitForStreamActivity($timeout)
    {
        $read = $this->readStreams;
        $write = $this->writeStreams;
        $available = $this->streamSelect($read, $write, $timeout);
        if ($this->pcntlPoll) {
            \pcntl_signal_dispatch();
        }
        if (\false === $available) {
            // if a system call has been interrupted,
            // we cannot rely on it's outcome
            return;
        }
        foreach ($read as $stream) {
            $key = (int) $stream;
            if (isset($this->readListeners[$key])) {
                \call_user_func($this->readListeners[$key], $stream);
            }
        }
        foreach ($write as $stream) {
            $key = (int) $stream;
            if (isset($this->writeListeners[$key])) {
                \call_user_func($this->writeListeners[$key], $stream);
            }
        }
    }
    /**
     * Emulate a stream_select() implementation that does not break when passed
     * empty stream arrays.
     *
     * @param array    $read    An array of read streams to select upon.
     * @param array    $write   An array of write streams to select upon.
     * @param int|null $timeout Activity timeout in microseconds, or null to wait forever.
     *
     * @return int|false The total number of streams that are ready for read/write.
     *     Can return false if stream_select() is interrupted by a signal.
     */
    private function streamSelect(array &$read, array &$write, $timeout)
    {
        if ($read || $write) {
            // We do not usually use or expose the `exceptfds` parameter passed to the underlying `select`.
            // However, Windows does not report failed connection attempts in `writefds` passed to `select` like most other platforms.
            // Instead, it uses `writefds` only for successful connection attempts and `exceptfds` for failed connection attempts.
            // We work around this by adding all sockets that look like a pending connection attempt to `exceptfds` automatically on Windows and merge it back later.
            // This ensures the public API matches other loop implementations across all platforms (see also test suite or rather test matrix).
            // Lacking better APIs, every write-only socket that has not yet read any data is assumed to be in a pending connection attempt state.
            // @link https://docs.microsoft.com/de-de/windows/win32/api/winsock2/nf-winsock2-select
            $except = null;
            if (\DIRECTORY_SEPARATOR === '\\') {
                $except = array();
                foreach ($write as $key => $socket) {
                    if (!isset($read[$key]) && @\ftell($socket) === 0) {
                        $except[$key] = $socket;
                    }
                }
            }
            /** @var ?callable $previous */
            $previous = \set_error_handler(function ($errno, $errstr) use (&$previous) {
                // suppress warnings that occur when `stream_select()` is interrupted by a signal
                // PHP defines `EINTR` through `ext-sockets` or `ext-pcntl`, otherwise use common default (Linux & Mac)
                $eintr = \defined('SOCKET_EINTR') ? \SOCKET_EINTR : (\defined('PCNTL_EINTR') ? \PCNTL_EINTR : 4);
                if ($errno === \E_WARNING && \strpos($errstr, '[' . $eintr . ']: ') !== \false) {
                    return;
                }
                // forward any other error to registered error handler or print warning
                return $previous !== null ? \call_user_func_array($previous, \func_get_args()) : \false;
            });
            try {
                $ret = \stream_select($read, $write, $except, $timeout === null ? null : 0, $timeout);
                \restore_error_handler();
            } catch (\Throwable $e) {
                // @codeCoverageIgnoreStart
                \restore_error_handler();
                throw $e;
            } catch (\Exception $e) {
                \restore_error_handler();
                throw $e;
            }
            // @codeCoverageIgnoreEnd
            if ($except) {
                $write = \array_merge($write, $except);
            }
            return $ret;
        }
        if ($timeout > 0) {
            \usleep($timeout);
        } elseif ($timeout === null) {
            // wait forever (we only reach this if we're only awaiting signals)
            // this may be interrupted and return earlier when a signal is received
            \sleep(\PHP_INT_MAX);
        }
        return 0;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Tick;

use SplQueue;
/**
 * A tick queue implementation that can hold multiple callback functions
 *
 * This class should only be used internally, see LoopInterface instead.
 *
 * @see LoopInterface
 * @internal
 */
final class FutureTickQueue
{
    private $queue;
    public function __construct()
    {
        $this->queue = new SplQueue();
    }
    /**
     * Add a callback to be invoked on a future tick of the event loop.
     *
     * Callbacks are guaranteed to be executed in the order they are enqueued.
     *
     * @param callable $listener The callback to invoke.
     */
    public function add($listener)
    {
        $this->queue->enqueue($listener);
    }
    /**
     * Flush the callback queue.
     */
    public function tick()
    {
        // Only invoke as many callbacks as were on the queue when tick() was called.
        $count = $this->queue->count();
        while ($count--) {
            \call_user_func($this->queue->dequeue());
        }
    }
    /**
     * Check if the next tick queue is empty.
     *
     * @return boolean
     */
    public function isEmpty()
    {
        return $this->queue->isEmpty();
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Timer;

use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\TimerInterface;
/**
 * The actual connection implementation for TimerInterface
 *
 * This class should only be used internally, see TimerInterface instead.
 *
 * @see TimerInterface
 * @internal
 */
final class Timer implements TimerInterface
{
    const MIN_INTERVAL = 1.0E-6;
    private $interval;
    private $callback;
    private $periodic;
    /**
     * Constructor initializes the fields of the Timer
     *
     * @param float         $interval The interval after which this timer will execute, in seconds
     * @param callable      $callback The callback that will be executed when this timer elapses
     * @param bool          $periodic Whether the time is periodic
     */
    public function __construct($interval, $callback, $periodic = \false)
    {
        if ($interval < self::MIN_INTERVAL) {
            $interval = self::MIN_INTERVAL;
        }
        $this->interval = (float) $interval;
        $this->callback = $callback;
        $this->periodic = (bool) $periodic;
    }
    public function getInterval()
    {
        return $this->interval;
    }
    public function getCallback()
    {
        return $this->callback;
    }
    public function isPeriodic()
    {
        return $this->periodic;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Timer;

use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\TimerInterface;
/**
 * A scheduler implementation that can hold multiple timer instances
 *
 * This class should only be used internally, see TimerInterface instead.
 *
 * @see TimerInterface
 * @internal
 */
final class Timers
{
    private $time;
    private $timers = array();
    private $schedule = array();
    private $sorted = \true;
    private $useHighResolution;
    public function __construct()
    {
        // prefer high-resolution timer, available as of PHP 7.3+
        $this->useHighResolution = \function_exists('hrtime');
    }
    public function updateTime()
    {
        return $this->time = $this->useHighResolution ? \hrtime(\true) * 1.0E-9 : \microtime(\true);
    }
    public function getTime()
    {
        return $this->time ?: $this->updateTime();
    }
    public function add(TimerInterface $timer)
    {
        $id = \PHP_VERSION_ID < 70200 ? \spl_object_hash($timer) : \spl_object_id($timer);
        $this->timers[$id] = $timer;
        $this->schedule[$id] = $timer->getInterval() + $this->updateTime();
        $this->sorted = \false;
    }
    public function contains(TimerInterface $timer)
    {
        $id = \PHP_VERSION_ID < 70200 ? \spl_object_hash($timer) : \spl_object_id($timer);
        return isset($this->timers[$id]);
    }
    public function cancel(TimerInterface $timer)
    {
        $id = \PHP_VERSION_ID < 70200 ? \spl_object_hash($timer) : \spl_object_id($timer);
        unset($this->timers[$id], $this->schedule[$id]);
    }
    public function getFirst()
    {
        // ensure timers are sorted to simply accessing next (first) one
        if (!$this->sorted) {
            $this->sorted = \true;
            \asort($this->schedule);
        }
        return \reset($this->schedule);
    }
    public function isEmpty()
    {
        return \count($this->timers) === 0;
    }
    public function tick()
    {
        // hot path: skip timers if nothing is scheduled
        if (!$this->schedule) {
            return;
        }
        // ensure timers are sorted so we can execute in order
        if (!$this->sorted) {
            $this->sorted = \true;
            \asort($this->schedule);
        }
        $time = $this->updateTime();
        foreach ($this->schedule as $id => $scheduled) {
            // schedule is ordered, so loop until first timer that is not scheduled for execution now
            if ($scheduled >= $time) {
                break;
            }
            // skip any timers that are removed while we process the current schedule
            if (!isset($this->schedule[$id]) || $this->schedule[$id] !== $scheduled) {
                continue;
            }
            $timer = $this->timers[$id];
            \call_user_func($timer->getCallback(), $timer);
            // re-schedule if this is a periodic timer and it has not been cancelled explicitly already
            if ($timer->isPeriodic() && isset($this->timers[$id])) {
                $this->schedule[$id] = $timer->getInterval() + $time;
                $this->sorted = \false;
            } else {
                unset($this->timers[$id], $this->schedule[$id]);
            }
        }
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\EventLoop;

interface TimerInterface
{
    /**
     * Get the interval after which this timer will execute, in seconds
     *
     * @return float
     */
    public function getInterval();
    /**
     * Get the callback that will be executed when this timer elapses
     *
     * @return callable
     */
    public function getCallback();
    /**
     * Determine whether the time is periodic
     *
     * @return bool
     */
    public function isPeriodic();
}
The MIT License (MIT)

Copyright (c) 2012 Christian Lück, Cees-Jan Kiewiet, Jan Sorgalla, Chris Boden, Igor Wiedler

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http;

use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\ResponseInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Loop;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Io\Sender;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Io\Transaction;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Message\Request;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Message\Uri;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\PromiseInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Socket\Connector;
use NightwatchAgent_kden27khxA4QoEfj\React\Socket\ConnectorInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\ReadableStreamInterface;
use InvalidArgumentException;
/**
 * @final This class is final and shouldn't be extended as it is likely to be marked final in a future release.
 */
class Browser
{
    private $transaction;
    private $baseUrl;
    private $protocolVersion = '1.1';
    private $defaultHeaders = array('User-Agent' => 'ReactPHP/1');
    /**
     * The `Browser` is responsible for sending HTTP requests to your HTTP server
     * and keeps track of pending incoming HTTP responses.
     *
     * ```php
     * $browser = new React\Http\Browser();
     * ```
     *
     * This class takes two optional arguments for more advanced usage:
     *
     * ```php
     * // constructor signature as of v1.5.0
     * $browser = new React\Http\Browser(?ConnectorInterface $connector = null, ?LoopInterface $loop = null);
     *
     * // legacy constructor signature before v1.5.0
     * $browser = new React\Http\Browser(?LoopInterface $loop = null, ?ConnectorInterface $connector = null);
     * ```
     *
     * If you need custom connector settings (DNS resolution, TLS parameters, timeouts,
     * proxy servers etc.), you can explicitly pass a custom instance of the
     * [`ConnectorInterface`](https://github.com/reactphp/socket#connectorinterface):
     *
     * ```php
     * $connector = new React\Socket\Connector(array(
     *     'dns' => '127.0.0.1',
     *     'tcp' => array(
     *         'bindto' => '192.168.10.1:0'
     *     ),
     *     'tls' => array(
     *         'verify_peer' => false,
     *         'verify_peer_name' => false
     *     )
     * ));
     *
     * $browser = new React\Http\Browser($connector);
     * ```
     *
     * This class takes an optional `LoopInterface|null $loop` parameter that can be used to
     * pass the event loop instance to use for this object. You can use a `null` value
     * here in order to use the [default loop](https://github.com/reactphp/event-loop#loop).
     * This value SHOULD NOT be given unless you're sure you want to explicitly use a
     * given event loop instance.
     *
     * @param null|ConnectorInterface|LoopInterface $connector
     * @param null|LoopInterface|ConnectorInterface $loop
     * @throws \InvalidArgumentException for invalid arguments
     */
    public function __construct($connector = null, $loop = null)
    {
        // swap arguments for legacy constructor signature
        if (($connector instanceof LoopInterface || $connector === null) && ($loop instanceof ConnectorInterface || $loop === null)) {
            $swap = $loop;
            $loop = $connector;
            $connector = $swap;
        }
        if ($connector !== null && !$connector instanceof ConnectorInterface || $loop !== null && !$loop instanceof LoopInterface) {
            throw new \InvalidArgumentException('Expected "?ConnectorInterface $connector" and "?LoopInterface $loop" arguments');
        }
        $loop = $loop ?: Loop::get();
        $this->transaction = new Transaction(Sender::createFromLoop($loop, $connector ?: new Connector(array(), $loop)), $loop);
    }
    /**
     * Sends an HTTP GET request
     *
     * ```php
     * $browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) {
     *     var_dump((string)$response->getBody());
     * }, function (Exception $e) {
     *     echo 'Error: ' . $e->getMessage() . PHP_EOL;
     * });
     * ```
     *
     * See also [GET request client example](../examples/01-client-get-request.php).
     *
     * @param string $url     URL for the request.
     * @param array  $headers
     * @return PromiseInterface<ResponseInterface>
     */
    public function get($url, array $headers = array())
    {
        return $this->requestMayBeStreaming('GET', $url, $headers);
    }
    /**
     * Sends an HTTP POST request
     *
     * ```php
     * $browser->post(
     *     $url,
     *     [
     *         'Content-Type' => 'application/json'
     *     ],
     *     json_encode($data)
     * )->then(function (Psr\Http\Message\ResponseInterface $response) {
     *     var_dump(json_decode((string)$response->getBody()));
     * }, function (Exception $e) {
     *     echo 'Error: ' . $e->getMessage() . PHP_EOL;
     * });
     * ```
     *
     * See also [POST JSON client example](../examples/04-client-post-json.php).
     *
     * This method is also commonly used to submit HTML form data:
     *
     * ```php
     * $data = [
     *     'user' => 'Alice',
     *     'password' => 'secret'
     * ];
     *
     * $browser->post(
     *     $url,
     *     [
     *         'Content-Type' => 'application/x-www-form-urlencoded'
     *     ],
     *     http_build_query($data)
     * );
     * ```
     *
     * This method will automatically add a matching `Content-Length` request
     * header if the outgoing request body is a `string`. If you're using a
     * streaming request body (`ReadableStreamInterface`), it will default to
     * using `Transfer-Encoding: chunked` or you have to explicitly pass in a
     * matching `Content-Length` request header like so:
     *
     * ```php
     * $body = new React\Stream\ThroughStream();
     * Loop::addTimer(1.0, function () use ($body) {
     *     $body->end("hello world");
     * });
     *
     * $browser->post($url, array('Content-Length' => '11'), $body);
     * ```
     *
     * @param string                         $url      URL for the request.
     * @param array                          $headers
     * @param string|ReadableStreamInterface $body
     * @return PromiseInterface<ResponseInterface>
     */
    public function post($url, array $headers = array(), $body = '')
    {
        return $this->requestMayBeStreaming('POST', $url, $headers, $body);
    }
    /**
     * Sends an HTTP HEAD request
     *
     * ```php
     * $browser->head($url)->then(function (Psr\Http\Message\ResponseInterface $response) {
     *     var_dump($response->getHeaders());
     * }, function (Exception $e) {
     *     echo 'Error: ' . $e->getMessage() . PHP_EOL;
     * });
     * ```
     *
     * @param string $url     URL for the request.
     * @param array  $headers
     * @return PromiseInterface<ResponseInterface>
     */
    public function head($url, array $headers = array())
    {
        return $this->requestMayBeStreaming('HEAD', $url, $headers);
    }
    /**
     * Sends an HTTP PATCH request
     *
     * ```php
     * $browser->patch(
     *     $url,
     *     [
     *         'Content-Type' => 'application/json'
     *     ],
     *     json_encode($data)
     * )->then(function (Psr\Http\Message\ResponseInterface $response) {
     *     var_dump(json_decode((string)$response->getBody()));
     * }, function (Exception $e) {
     *     echo 'Error: ' . $e->getMessage() . PHP_EOL;
     * });
     * ```
     *
     * This method will automatically add a matching `Content-Length` request
     * header if the outgoing request body is a `string`. If you're using a
     * streaming request body (`ReadableStreamInterface`), it will default to
     * using `Transfer-Encoding: chunked` or you have to explicitly pass in a
     * matching `Content-Length` request header like so:
     *
     * ```php
     * $body = new React\Stream\ThroughStream();
     * Loop::addTimer(1.0, function () use ($body) {
     *     $body->end("hello world");
     * });
     *
     * $browser->patch($url, array('Content-Length' => '11'), $body);
     * ```
     *
     * @param string                         $url      URL for the request.
     * @param array                          $headers
     * @param string|ReadableStreamInterface $body
     * @return PromiseInterface<ResponseInterface>
     */
    public function patch($url, array $headers = array(), $body = '')
    {
        return $this->requestMayBeStreaming('PATCH', $url, $headers, $body);
    }
    /**
     * Sends an HTTP PUT request
     *
     * ```php
     * $browser->put(
     *     $url,
     *     [
     *         'Content-Type' => 'text/xml'
     *     ],
     *     $xml->asXML()
     * )->then(function (Psr\Http\Message\ResponseInterface $response) {
     *     var_dump((string)$response->getBody());
     * }, function (Exception $e) {
     *     echo 'Error: ' . $e->getMessage() . PHP_EOL;
     * });
     * ```
     *
     * See also [PUT XML client example](../examples/05-client-put-xml.php).
     *
     * This method will automatically add a matching `Content-Length` request
     * header if the outgoing request body is a `string`. If you're using a
     * streaming request body (`ReadableStreamInterface`), it will default to
     * using `Transfer-Encoding: chunked` or you have to explicitly pass in a
     * matching `Content-Length` request header like so:
     *
     * ```php
     * $body = new React\Stream\ThroughStream();
     * Loop::addTimer(1.0, function () use ($body) {
     *     $body->end("hello world");
     * });
     *
     * $browser->put($url, array('Content-Length' => '11'), $body);
     * ```
     *
     * @param string                         $url      URL for the request.
     * @param array                          $headers
     * @param string|ReadableStreamInterface $body
     * @return PromiseInterface<ResponseInterface>
     */
    public function put($url, array $headers = array(), $body = '')
    {
        return $this->requestMayBeStreaming('PUT', $url, $headers, $body);
    }
    /**
     * Sends an HTTP DELETE request
     *
     * ```php
     * $browser->delete($url)->then(function (Psr\Http\Message\ResponseInterface $response) {
     *     var_dump((string)$response->getBody());
     * }, function (Exception $e) {
     *     echo 'Error: ' . $e->getMessage() . PHP_EOL;
     * });
     * ```
     *
     * @param string                         $url      URL for the request.
     * @param array                          $headers
     * @param string|ReadableStreamInterface $body
     * @return PromiseInterface<ResponseInterface>
     */
    public function delete($url, array $headers = array(), $body = '')
    {
        return $this->requestMayBeStreaming('DELETE', $url, $headers, $body);
    }
    /**
     * Sends an arbitrary HTTP request.
     *
     * The preferred way to send an HTTP request is by using the above
     * [request methods](#request-methods), for example the [`get()`](#get)
     * method to send an HTTP `GET` request.
     *
     * As an alternative, if you want to use a custom HTTP request method, you
     * can use this method:
     *
     * ```php
     * $browser->request('OPTIONS', $url)->then(function (Psr\Http\Message\ResponseInterface $response) {
     *     var_dump((string)$response->getBody());
     * }, function (Exception $e) {
     *     echo 'Error: ' . $e->getMessage() . PHP_EOL;
     * });
     * ```
     *
     * This method will automatically add a matching `Content-Length` request
     * header if the size of the outgoing request body is known and non-empty.
     * For an empty request body, if will only include a `Content-Length: 0`
     * request header if the request method usually expects a request body (only
     * applies to `POST`, `PUT` and `PATCH`).
     *
     * If you're using a streaming request body (`ReadableStreamInterface`), it
     * will default to using `Transfer-Encoding: chunked` or you have to
     * explicitly pass in a matching `Content-Length` request header like so:
     *
     * ```php
     * $body = new React\Stream\ThroughStream();
     * Loop::addTimer(1.0, function () use ($body) {
     *     $body->end("hello world");
     * });
     *
     * $browser->request('POST', $url, array('Content-Length' => '11'), $body);
     * ```
     *
     * @param string                         $method   HTTP request method, e.g. GET/HEAD/POST etc.
     * @param string                         $url      URL for the request
     * @param array                          $headers  Additional request headers
     * @param string|ReadableStreamInterface $body     HTTP request body contents
     * @return PromiseInterface<ResponseInterface>
     */
    public function request($method, $url, array $headers = array(), $body = '')
    {
        return $this->withOptions(array('streaming' => \false))->requestMayBeStreaming($method, $url, $headers, $body);
    }
    /**
     * Sends an arbitrary HTTP request and receives a streaming response without buffering the response body.
     *
     * The preferred way to send an HTTP request is by using the above
     * [request methods](#request-methods), for example the [`get()`](#get)
     * method to send an HTTP `GET` request. Each of these methods will buffer
     * the whole response body in memory by default. This is easy to get started
     * and works reasonably well for smaller responses.
     *
     * In some situations, it's a better idea to use a streaming approach, where
     * only small chunks have to be kept in memory. You can use this method to
     * send an arbitrary HTTP request and receive a streaming response. It uses
     * the same HTTP message API, but does not buffer the response body in
     * memory. It only processes the response body in small chunks as data is
     * received and forwards this data through [ReactPHP's Stream API](https://github.com/reactphp/stream).
     * This works for (any number of) responses of arbitrary sizes.
     *
     * ```php
     * $browser->requestStreaming('GET', $url)->then(function (Psr\Http\Message\ResponseInterface $response) {
     *     $body = $response->getBody();
     *     assert($body instanceof Psr\Http\Message\StreamInterface);
     *     assert($body instanceof React\Stream\ReadableStreamInterface);
     *
     *     $body->on('data', function ($chunk) {
     *         echo $chunk;
     *     });
     *
     *     $body->on('error', function (Exception $e) {
     *         echo 'Error: ' . $e->getMessage() . PHP_EOL;
     *     });
     *
     *     $body->on('close', function () {
     *         echo '[DONE]' . PHP_EOL;
     *     });
     * }, function (Exception $e) {
     *     echo 'Error: ' . $e->getMessage() . PHP_EOL;
     * });
     * ```
     *
     * See also [`ReadableStreamInterface`](https://github.com/reactphp/stream#readablestreaminterface)
     * and the [streaming response](#streaming-response) for more details,
     * examples and possible use-cases.
     *
     * This method will automatically add a matching `Content-Length` request
     * header if the size of the outgoing request body is known and non-empty.
     * For an empty request body, if will only include a `Content-Length: 0`
     * request header if the request method usually expects a request body (only
     * applies to `POST`, `PUT` and `PATCH`).
     *
     * If you're using a streaming request body (`ReadableStreamInterface`), it
     * will default to using `Transfer-Encoding: chunked` or you have to
     * explicitly pass in a matching `Content-Length` request header like so:
     *
     * ```php
     * $body = new React\Stream\ThroughStream();
     * Loop::addTimer(1.0, function () use ($body) {
     *     $body->end("hello world");
     * });
     *
     * $browser->requestStreaming('POST', $url, array('Content-Length' => '11'), $body);
     * ```
     *
     * @param string                         $method   HTTP request method, e.g. GET/HEAD/POST etc.
     * @param string                         $url      URL for the request
     * @param array                          $headers  Additional request headers
     * @param string|ReadableStreamInterface $body     HTTP request body contents
     * @return PromiseInterface<ResponseInterface>
     */
    public function requestStreaming($method, $url, $headers = array(), $body = '')
    {
        return $this->withOptions(array('streaming' => \true))->requestMayBeStreaming($method, $url, $headers, $body);
    }
    /**
     * Changes the maximum timeout used for waiting for pending requests.
     *
     * You can pass in the number of seconds to use as a new timeout value:
     *
     * ```php
     * $browser = $browser->withTimeout(10.0);
     * ```
     *
     * You can pass in a bool `false` to disable any timeouts. In this case,
     * requests can stay pending forever:
     *
     * ```php
     * $browser = $browser->withTimeout(false);
     * ```
     *
     * You can pass in a bool `true` to re-enable default timeout handling. This
     * will respects PHP's `default_socket_timeout` setting (default 60s):
     *
     * ```php
     * $browser = $browser->withTimeout(true);
     * ```
     *
     * See also [timeouts](#timeouts) for more details about timeout handling.
     *
     * Notice that the [`Browser`](#browser) is an immutable object, i.e. this
     * method actually returns a *new* [`Browser`](#browser) instance with the
     * given timeout value applied.
     *
     * @param bool|number $timeout
     * @return self
     */
    public function withTimeout($timeout)
    {
        if ($timeout === \true) {
            $timeout = null;
        } elseif ($timeout === \false) {
            $timeout = -1;
        } elseif ($timeout < 0) {
            $timeout = 0;
        }
        return $this->withOptions(array('timeout' => $timeout));
    }
    /**
     * Changes how HTTP redirects will be followed.
     *
     * You can pass in the maximum number of redirects to follow:
     *
     * ```php
     * $browser = $browser->withFollowRedirects(5);
     * ```
     *
     * The request will automatically be rejected when the number of redirects
     * is exceeded. You can pass in a `0` to reject the request for any
     * redirects encountered:
     *
     * ```php
     * $browser = $browser->withFollowRedirects(0);
     *
     * $browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) {
     *     // only non-redirected responses will now end up here
     *     var_dump($response->getHeaders());
     * }, function (Exception $e) {
     *     echo 'Error: ' . $e->getMessage() . PHP_EOL;
     * });
     * ```
     *
     * You can pass in a bool `false` to disable following any redirects. In
     * this case, requests will resolve with the redirection response instead
     * of following the `Location` response header:
     *
     * ```php
     * $browser = $browser->withFollowRedirects(false);
     *
     * $browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) {
     *     // any redirects will now end up here
     *     var_dump($response->getHeaderLine('Location'));
     * }, function (Exception $e) {
     *     echo 'Error: ' . $e->getMessage() . PHP_EOL;
     * });
     * ```
     *
     * You can pass in a bool `true` to re-enable default redirect handling.
     * This defaults to following a maximum of 10 redirects:
     *
     * ```php
     * $browser = $browser->withFollowRedirects(true);
     * ```
     *
     * See also [redirects](#redirects) for more details about redirect handling.
     *
     * Notice that the [`Browser`](#browser) is an immutable object, i.e. this
     * method actually returns a *new* [`Browser`](#browser) instance with the
     * given redirect setting applied.
     *
     * @param bool|int $followRedirects
     * @return self
     */
    public function withFollowRedirects($followRedirects)
    {
        return $this->withOptions(array('followRedirects' => $followRedirects !== \false, 'maxRedirects' => \is_bool($followRedirects) ? null : $followRedirects));
    }
    /**
     * Changes whether non-successful HTTP response status codes (4xx and 5xx) will be rejected.
     *
     * You can pass in a bool `false` to disable rejecting incoming responses
     * that use a 4xx or 5xx response status code. In this case, requests will
     * resolve with the response message indicating an error condition:
     *
     * ```php
     * $browser = $browser->withRejectErrorResponse(false);
     *
     * $browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) {
     *     // any HTTP response will now end up here
     *     var_dump($response->getStatusCode(), $response->getReasonPhrase());
     * }, function (Exception $e) {
     *     echo 'Error: ' . $e->getMessage() . PHP_EOL;
     * });
     * ```
     *
     * You can pass in a bool `true` to re-enable default status code handling.
     * This defaults to rejecting any response status codes in the 4xx or 5xx
     * range:
     *
     * ```php
     * $browser = $browser->withRejectErrorResponse(true);
     *
     * $browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) {
     *     // any successful HTTP response will now end up here
     *     var_dump($response->getStatusCode(), $response->getReasonPhrase());
     * }, function (Exception $e) {
     *     if ($e instanceof React\Http\Message\ResponseException) {
     *         // any HTTP response error message will now end up here
     *         $response = $e->getResponse();
     *         var_dump($response->getStatusCode(), $response->getReasonPhrase());
     *     } else {
     *         echo 'Error: ' . $e->getMessage() . PHP_EOL;
     *     }
     * });
     * ```
     *
     * Notice that the [`Browser`](#browser) is an immutable object, i.e. this
     * method actually returns a *new* [`Browser`](#browser) instance with the
     * given setting applied.
     *
     * @param bool $obeySuccessCode
     * @return self
     */
    public function withRejectErrorResponse($obeySuccessCode)
    {
        return $this->withOptions(array('obeySuccessCode' => $obeySuccessCode));
    }
    /**
     * Changes the base URL used to resolve relative URLs to.
     *
     * If you configure a base URL, any requests to relative URLs will be
     * processed by first resolving this relative to the given absolute base
     * URL. This supports resolving relative path references (like `../` etc.).
     * This is particularly useful for (RESTful) API calls where all endpoints
     * (URLs) are located under a common base URL.
     *
     * ```php
     * $browser = $browser->withBase('http://api.example.com/v3/');
     *
     * // will request http://api.example.com/v3/users
     * $browser->get('users')->then(…);
     * ```
     *
     * You can pass in a `null` base URL to return a new instance that does not
     * use a base URL:
     *
     * ```php
     * $browser = $browser->withBase(null);
     * ```
     *
     * Accordingly, any requests using relative URLs to a browser that does not
     * use a base URL can not be completed and will be rejected without sending
     * a request.
     *
     * This method will throw an `InvalidArgumentException` if the given
     * `$baseUrl` argument is not a valid URL.
     *
     * Notice that the [`Browser`](#browser) is an immutable object, i.e. the `withBase()` method
     * actually returns a *new* [`Browser`](#browser) instance with the given base URL applied.
     *
     * @param string|null $baseUrl absolute base URL
     * @return self
     * @throws InvalidArgumentException if the given $baseUrl is not a valid absolute URL
     * @see self::withoutBase()
     */
    public function withBase($baseUrl)
    {
        $browser = clone $this;
        if ($baseUrl === null) {
            $browser->baseUrl = null;
            return $browser;
        }
        $browser->baseUrl = new Uri($baseUrl);
        if (!\in_array($browser->baseUrl->getScheme(), array('http', 'https')) || $browser->baseUrl->getHost() === '') {
            throw new \InvalidArgumentException('Base URL must be absolute');
        }
        return $browser;
    }
    /**
     * Changes the HTTP protocol version that will be used for all subsequent requests.
     *
     * All the above [request methods](#request-methods) default to sending
     * requests as HTTP/1.1. This is the preferred HTTP protocol version which
     * also provides decent backwards-compatibility with legacy HTTP/1.0
     * servers. As such, there should rarely be a need to explicitly change this
     * protocol version.
     *
     * If you want to explicitly use the legacy HTTP/1.0 protocol version, you
     * can use this method:
     *
     * ```php
     * $browser = $browser->withProtocolVersion('1.0');
     *
     * $browser->get($url)->then(…);
     * ```
     *
     * Notice that the [`Browser`](#browser) is an immutable object, i.e. this
     * method actually returns a *new* [`Browser`](#browser) instance with the
     * new protocol version applied.
     *
     * @param string $protocolVersion HTTP protocol version to use, must be one of "1.1" or "1.0"
     * @return self
     * @throws InvalidArgumentException
     */
    public function withProtocolVersion($protocolVersion)
    {
        if (!\in_array($protocolVersion, array('1.0', '1.1'), \true)) {
            throw new InvalidArgumentException('Invalid HTTP protocol version, must be one of "1.1" or "1.0"');
        }
        $browser = clone $this;
        $browser->protocolVersion = (string) $protocolVersion;
        return $browser;
    }
    /**
     * Changes the maximum size for buffering a response body.
     *
     * The preferred way to send an HTTP request is by using the above
     * [request methods](#request-methods), for example the [`get()`](#get)
     * method to send an HTTP `GET` request. Each of these methods will buffer
     * the whole response body in memory by default. This is easy to get started
     * and works reasonably well for smaller responses.
     *
     * By default, the response body buffer will be limited to 16 MiB. If the
     * response body exceeds this maximum size, the request will be rejected.
     *
     * You can pass in the maximum number of bytes to buffer:
     *
     * ```php
     * $browser = $browser->withResponseBuffer(1024 * 1024);
     *
     * $browser->get($url)->then(function (Psr\Http\Message\ResponseInterface $response) {
     *     // response body will not exceed 1 MiB
     *     var_dump($response->getHeaders(), (string) $response->getBody());
     * }, function (Exception $e) {
     *     echo 'Error: ' . $e->getMessage() . PHP_EOL;
     * });
     * ```
     *
     * Note that the response body buffer has to be kept in memory for each
     * pending request until its transfer is completed and it will only be freed
     * after a pending request is fulfilled. As such, increasing this maximum
     * buffer size to allow larger response bodies is usually not recommended.
     * Instead, you can use the [`requestStreaming()` method](#requeststreaming)
     * to receive responses with arbitrary sizes without buffering. Accordingly,
     * this maximum buffer size setting has no effect on streaming responses.
     *
     * Notice that the [`Browser`](#browser) is an immutable object, i.e. this
     * method actually returns a *new* [`Browser`](#browser) instance with the
     * given setting applied.
     *
     * @param int $maximumSize
     * @return self
     * @see self::requestStreaming()
     */
    public function withResponseBuffer($maximumSize)
    {
        return $this->withOptions(array('maximumSize' => $maximumSize));
    }
    /**
     * Add a request header for all following requests.
     *
     * ```php
     * $browser = $browser->withHeader('User-Agent', 'ACME');
     *
     * $browser->get($url)->then(…);
     * ```
     *
     * Note that the new header will overwrite any headers previously set with
     * the same name (case-insensitive). Following requests will use these headers
     * by default unless they are explicitly set for any requests.
     *
     * @param string $header
     * @param string $value
     * @return Browser
     */
    public function withHeader($header, $value)
    {
        $browser = $this->withoutHeader($header);
        $browser->defaultHeaders[$header] = $value;
        return $browser;
    }
    /**
     * Remove any default request headers previously set via
     * the [`withHeader()` method](#withheader).
     *
     * ```php
     * $browser = $browser->withoutHeader('User-Agent');
     *
     * $browser->get($url)->then(…);
     * ```
     *
     * Note that this method only affects the headers which were set with the
     * method `withHeader(string $header, string $value): Browser`
     *
     * @param string $header
     * @return Browser
     */
    public function withoutHeader($header)
    {
        $browser = clone $this;
        /** @var string|int $key */
        foreach (\array_keys($browser->defaultHeaders) as $key) {
            if (\strcasecmp($key, $header) === 0) {
                unset($browser->defaultHeaders[$key]);
                break;
            }
        }
        return $browser;
    }
    /**
     * Changes the [options](#options) to use:
     *
     * The [`Browser`](#browser) class exposes several options for the handling of
     * HTTP transactions. These options resemble some of PHP's
     * [HTTP context options](http://php.net/manual/en/context.http.php) and
     * can be controlled via the following API (and their defaults):
     *
     * ```php
     * // deprecated
     * $newBrowser = $browser->withOptions(array(
     *     'timeout' => null, // see withTimeout() instead
     *     'followRedirects' => true, // see withFollowRedirects() instead
     *     'maxRedirects' => 10, // see withFollowRedirects() instead
     *     'obeySuccessCode' => true, // see withRejectErrorResponse() instead
     *     'streaming' => false, // deprecated, see requestStreaming() instead
     * ));
     * ```
     *
     * See also [timeouts](#timeouts), [redirects](#redirects) and
     * [streaming](#streaming) for more details.
     *
     * Notice that the [`Browser`](#browser) is an immutable object, i.e. this
     * method actually returns a *new* [`Browser`](#browser) instance with the
     * options applied.
     *
     * @param array $options
     * @return self
     * @see self::withTimeout()
     * @see self::withFollowRedirects()
     * @see self::withRejectErrorResponse()
     */
    private function withOptions(array $options)
    {
        $browser = clone $this;
        $browser->transaction = $this->transaction->withOptions($options);
        return $browser;
    }
    /**
     * @param string                         $method
     * @param string                         $url
     * @param array                          $headers
     * @param string|ReadableStreamInterface $body
     * @return PromiseInterface<ResponseInterface>
     */
    private function requestMayBeStreaming($method, $url, array $headers = array(), $body = '')
    {
        if ($this->baseUrl !== null) {
            // ensure we're actually below the base URL
            $url = Uri::resolve($this->baseUrl, new Uri($url));
        }
        foreach ($this->defaultHeaders as $key => $value) {
            $explicitHeaderExists = \false;
            foreach (\array_keys($headers) as $headerKey) {
                if (\strcasecmp($headerKey, $key) === 0) {
                    $explicitHeaderExists = \true;
                    break;
                }
            }
            if (!$explicitHeaderExists) {
                $headers[$key] = $value;
            }
        }
        return $this->transaction->send(new Request($method, $url, $headers, $body, $this->protocolVersion));
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Client;

use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\RequestInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Io\ClientConnectionManager;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Io\ClientRequestStream;
/**
 * @internal
 */
class Client
{
    /** @var ClientConnectionManager */
    private $connectionManager;
    public function __construct(ClientConnectionManager $connectionManager)
    {
        $this->connectionManager = $connectionManager;
    }
    /** @return ClientRequestStream */
    public function request(RequestInterface $request)
    {
        return new ClientRequestStream($this->connectionManager, $request);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Loop;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Io\IniUtil;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Io\MiddlewareRunner;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Io\StreamingServer;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Middleware\LimitConcurrentRequestsMiddleware;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Middleware\StreamingRequestMiddleware;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Middleware\RequestBodyBufferMiddleware;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Middleware\RequestBodyParserMiddleware;
use NightwatchAgent_kden27khxA4QoEfj\React\Socket\ServerInterface;
/**
 * The `React\Http\HttpServer` class is responsible for handling incoming connections and then
 * processing each incoming HTTP request.
 *
 * When a complete HTTP request has been received, it will invoke the given
 * request handler function. This request handler function needs to be passed to
 * the constructor and will be invoked with the respective [request](#server-request)
 * object and expects a [response](#server-response) object in return:
 *
 * ```php
 * $http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) {
 *     return new React\Http\Message\Response(
 *         React\Http\Message\Response::STATUS_OK,
 *         array(
 *             'Content-Type' => 'text/plain'
 *         ),
 *         "Hello World!\n"
 *     );
 * });
 * ```
 *
 * Each incoming HTTP request message is always represented by the
 * [PSR-7 `ServerRequestInterface`](https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface),
 * see also following [request](#server-request) chapter for more details.
 *
 * Each outgoing HTTP response message is always represented by the
 * [PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface),
 * see also following [response](#server-response) chapter for more details.
 *
 * This class takes an optional `LoopInterface|null $loop` parameter that can be used to
 * pass the event loop instance to use for this object. You can use a `null` value
 * here in order to use the [default loop](https://github.com/reactphp/event-loop#loop).
 * This value SHOULD NOT be given unless you're sure you want to explicitly use a
 * given event loop instance.
 *
 * In order to start listening for any incoming connections, the `HttpServer` needs
 * to be attached to an instance of
 * [`React\Socket\ServerInterface`](https://github.com/reactphp/socket#serverinterface)
 * through the [`listen()`](#listen) method as described in the following
 * chapter. In its most simple form, you can attach this to a
 * [`React\Socket\SocketServer`](https://github.com/reactphp/socket#socketserver)
 * in order to start a plaintext HTTP server like this:
 *
 * ```php
 * $http = new React\Http\HttpServer($handler);
 *
 * $socket = new React\Socket\SocketServer('0.0.0.0:8080');
 * $http->listen($socket);
 * ```
 *
 * See also the [`listen()`](#listen) method and
 * [hello world server example](../examples/51-server-hello-world.php)
 * for more details.
 *
 * By default, the `HttpServer` buffers and parses the complete incoming HTTP
 * request in memory. It will invoke the given request handler function when the
 * complete request headers and request body has been received. This means the
 * [request](#server-request) object passed to your request handler function will be
 * fully compatible with PSR-7 (http-message). This provides sane defaults for
 * 80% of the use cases and is the recommended way to use this library unless
 * you're sure you know what you're doing.
 *
 * On the other hand, buffering complete HTTP requests in memory until they can
 * be processed by your request handler function means that this class has to
 * employ a number of limits to avoid consuming too much memory. In order to
 * take the more advanced configuration out your hand, it respects setting from
 * your [`php.ini`](https://www.php.net/manual/en/ini.core.php) to apply its
 * default settings. This is a list of PHP settings this class respects with
 * their respective default values:
 *
 * ```
 * memory_limit 128M
 * post_max_size 8M // capped at 64K
 *
 * enable_post_data_reading 1
 * max_input_nesting_level 64
 * max_input_vars 1000
 *
 * file_uploads 1
 * upload_max_filesize 2M
 * max_file_uploads 20
 * ```
 *
 * In particular, the `post_max_size` setting limits how much memory a single
 * HTTP request is allowed to consume while buffering its request body. This
 * needs to be limited because the server can process a large number of requests
 * concurrently, so the server may potentially consume a large amount of memory
 * otherwise. To support higher concurrency by default, this value is capped
 * at `64K`. If you assign a higher value, it will only allow `64K` by default.
 * If a request exceeds this limit, its request body will be ignored and it will
 * be processed like a request with no request body at all. See below for
 * explicit configuration to override this setting.
 *
 * By default, this class will try to avoid consuming more than half of your
 * `memory_limit` for buffering multiple concurrent HTTP requests. As such, with
 * the above default settings of `128M` max, it will try to consume no more than
 * `64M` for buffering multiple concurrent HTTP requests. As a consequence, it
 * will limit the concurrency to `1024` HTTP requests with the above defaults.
 *
 * It is imperative that you assign reasonable values to your PHP ini settings.
 * It is usually recommended to not support buffering incoming HTTP requests
 * with a large HTTP request body (e.g. large file uploads). If you want to
 * increase this buffer size, you will have to also increase the total memory
 * limit to allow for more concurrent requests (set `memory_limit 512M` or more)
 * or explicitly limit concurrency.
 *
 * In order to override the above buffering defaults, you can configure the
 * `HttpServer` explicitly. You can use the
 * [`LimitConcurrentRequestsMiddleware`](#limitconcurrentrequestsmiddleware) and
 * [`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware) (see below)
 * to explicitly configure the total number of requests that can be handled at
 * once like this:
 *
 * ```php
 * $http = new React\Http\HttpServer(
 *     new React\Http\Middleware\StreamingRequestMiddleware(),
 *     new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers
 *     new React\Http\Middleware\RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request
 *     new React\Http\Middleware\RequestBodyParserMiddleware(),
 *     $handler
 * ));
 * ```
 *
 * In this example, we allow processing up to 100 concurrent requests at once
 * and each request can buffer up to `2M`. This means you may have to keep a
 * maximum of `200M` of memory for incoming request body buffers. Accordingly,
 * you need to adjust the `memory_limit` ini setting to allow for these buffers
 * plus your actual application logic memory requirements (think `512M` or more).
 *
 * > Internally, this class automatically assigns these middleware handlers
 *   automatically when no [`StreamingRequestMiddleware`](#streamingrequestmiddleware)
 *   is given. Accordingly, you can use this example to override all default
 *   settings to implement custom limits.
 *
 * As an alternative to buffering the complete request body in memory, you can
 * also use a streaming approach where only small chunks of data have to be kept
 * in memory:
 *
 * ```php
 * $http = new React\Http\HttpServer(
 *     new React\Http\Middleware\StreamingRequestMiddleware(),
 *     $handler
 * );
 * ```
 *
 * In this case, it will invoke the request handler function once the HTTP
 * request headers have been received, i.e. before receiving the potentially
 * much larger HTTP request body. This means the [request](#server-request) passed to
 * your request handler function may not be fully compatible with PSR-7. This is
 * specifically designed to help with more advanced use cases where you want to
 * have full control over consuming the incoming HTTP request body and
 * concurrency settings. See also [streaming incoming request](#streaming-incoming-request)
 * below for more details.
 *
 * > Changelog v1.5.0: This class has been renamed to `HttpServer` from the
 *   previous `Server` class in order to avoid any ambiguities.
 *   The previous name has been deprecated and should not be used anymore.
 */
final class HttpServer extends EventEmitter
{
    /**
     * The maximum buffer size used for each request.
     *
     * This needs to be limited because the server can process a large number of
     * requests concurrently, so the server may potentially consume a large
     * amount of memory otherwise.
     *
     * See `RequestBodyBufferMiddleware` to override this setting.
     *
     * @internal
     */
    const MAXIMUM_BUFFER_SIZE = 65536;
    // 64 KiB
    /**
     * @var StreamingServer
     */
    private $streamingServer;
    /**
     * Creates an HTTP server that invokes the given callback for each incoming HTTP request
     *
     * In order to process any connections, the server needs to be attached to an
     * instance of `React\Socket\ServerInterface` which emits underlying streaming
     * connections in order to then parse incoming data as HTTP.
     * See also [listen()](#listen) for more details.
     *
     * @param callable|LoopInterface $requestHandlerOrLoop
     * @param callable[] ...$requestHandler
     * @see self::listen()
     */
    public function __construct($requestHandlerOrLoop)
    {
        $requestHandlers = \func_get_args();
        if (reset($requestHandlers) instanceof LoopInterface) {
            $loop = \array_shift($requestHandlers);
        } else {
            $loop = Loop::get();
        }
        $requestHandlersCount = \count($requestHandlers);
        if ($requestHandlersCount === 0 || \count(\array_filter($requestHandlers, 'is_callable')) < $requestHandlersCount) {
            throw new \InvalidArgumentException('Invalid request handler given');
        }
        $streaming = \false;
        foreach ((array) $requestHandlers as $handler) {
            if ($handler instanceof StreamingRequestMiddleware) {
                $streaming = \true;
                break;
            }
        }
        $middleware = array();
        if (!$streaming) {
            $maxSize = $this->getMaxRequestSize();
            $concurrency = $this->getConcurrentRequestsLimit(\ini_get('memory_limit'), $maxSize);
            if ($concurrency !== null) {
                $middleware[] = new LimitConcurrentRequestsMiddleware($concurrency);
            }
            $middleware[] = new RequestBodyBufferMiddleware($maxSize);
            // Checking for an empty string because that is what a boolean
            // false is returned as by ini_get depending on the PHP version.
            // @link http://php.net/manual/en/ini.core.php#ini.enable-post-data-reading
            // @link http://php.net/manual/en/function.ini-get.php#refsect1-function.ini-get-notes
            // @link https://3v4l.org/qJtsa
            $enablePostDataReading = \ini_get('enable_post_data_reading');
            if ($enablePostDataReading !== '') {
                $middleware[] = new RequestBodyParserMiddleware();
            }
        }
        $middleware = \array_merge($middleware, $requestHandlers);
        /**
         * Filter out any configuration middleware, no need to run requests through something that isn't
         * doing anything with the request.
         */
        $middleware = \array_filter($middleware, function ($handler) {
            return !$handler instanceof StreamingRequestMiddleware;
        });
        $this->streamingServer = new StreamingServer($loop, new MiddlewareRunner($middleware));
        $that = $this;
        $this->streamingServer->on('error', function ($error) use ($that) {
            $that->emit('error', array($error));
        });
    }
    /**
     * Starts listening for HTTP requests on the given socket server instance
     *
     * The given [`React\Socket\ServerInterface`](https://github.com/reactphp/socket#serverinterface)
     * is responsible for emitting the underlying streaming connections. This
     * HTTP server needs to be attached to it in order to process any
     * connections and pase incoming streaming data as incoming HTTP request
     * messages. In its most common form, you can attach this to a
     * [`React\Socket\SocketServer`](https://github.com/reactphp/socket#socketserver)
     * in order to start a plaintext HTTP server like this:
     *
     * ```php
     * $http = new React\Http\HttpServer($handler);
     *
     * $socket = new React\Socket\SocketServer('0.0.0.0:8080');
     * $http->listen($socket);
     * ```
     *
     * See also [hello world server example](../examples/51-server-hello-world.php)
     * for more details.
     *
     * This example will start listening for HTTP requests on the alternative
     * HTTP port `8080` on all interfaces (publicly). As an alternative, it is
     * very common to use a reverse proxy and let this HTTP server listen on the
     * localhost (loopback) interface only by using the listen address
     * `127.0.0.1:8080` instead. This way, you host your application(s) on the
     * default HTTP port `80` and only route specific requests to this HTTP
     * server.
     *
     * Likewise, it's usually recommended to use a reverse proxy setup to accept
     * secure HTTPS requests on default HTTPS port `443` (TLS termination) and
     * only route plaintext requests to this HTTP server. As an alternative, you
     * can also accept secure HTTPS requests with this HTTP server by attaching
     * this to a [`React\Socket\SocketServer`](https://github.com/reactphp/socket#socketserver)
     * using a secure TLS listen address, a certificate file and optional
     * `passphrase` like this:
     *
     * ```php
     * $http = new React\Http\HttpServer($handler);
     *
     * $socket = new React\Socket\SocketServer('tls://0.0.0.0:8443', array(
     *     'tls' => array(
     *         'local_cert' => __DIR__ . '/localhost.pem'
     *     )
     * ));
     * $http->listen($socket);
     * ```
     *
     * See also [hello world HTTPS example](../examples/61-server-hello-world-https.php)
     * for more details.
     *
     * @param ServerInterface $socket
     */
    public function listen(ServerInterface $socket)
    {
        $this->streamingServer->listen($socket);
    }
    /**
     * @param string $memory_limit
     * @param string $post_max_size
     * @return ?int
     */
    private function getConcurrentRequestsLimit($memory_limit, $post_max_size)
    {
        if ($memory_limit == -1) {
            return null;
        }
        $availableMemory = IniUtil::iniSizeToBytes($memory_limit) / 2;
        $concurrentRequests = (int) \ceil($availableMemory / IniUtil::iniSizeToBytes($post_max_size));
        return $concurrentRequests;
    }
    /**
     * @param ?string $post_max_size
     * @return int
     */
    private function getMaxRequestSize($post_max_size = null)
    {
        $maxSize = IniUtil::iniSizeToBytes($post_max_size === null ? \ini_get('post_max_size') : $post_max_size);
        return $maxSize === 0 || $maxSize >= self::MAXIMUM_BUFFER_SIZE ? self::MAXIMUM_BUFFER_SIZE : $maxSize;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Io;

use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\MessageInterface;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\StreamInterface;
/**
 * [Internal] Abstract HTTP message base class (PSR-7)
 *
 * @internal
 * @see MessageInterface
 */
abstract class AbstractMessage implements MessageInterface
{
    /**
     * [Internal] Regex used to match all request header fields into an array, thanks to @kelunik for checking the HTTP specs and coming up with this regex
     *
     * @internal
     * @var string
     */
    const REGEX_HEADERS = '/^([^()<>@,;:\\\\"\/\[\]?={}\x00-\x20\x7F]++):[\x20\x09]*+((?:[\x20\x09]*+[\x21-\x7E\x80-\xFF]++)*+)[\x20\x09]*+[\r]?+\n/m';
    /** @var array<string,string[]> */
    private $headers = array();
    /** @var array<string,string> */
    private $headerNamesLowerCase = array();
    /** @var string */
    private $protocolVersion;
    /** @var StreamInterface */
    private $body;
    /**
     * @param string $protocolVersion
     * @param array<string,string|string[]> $headers
     * @param StreamInterface $body
     */
    protected function __construct($protocolVersion, array $headers, StreamInterface $body)
    {
        foreach ($headers as $name => $value) {
            if ($value !== array()) {
                if (\is_array($value)) {
                    foreach ($value as &$one) {
                        $one = (string) $one;
                    }
                } else {
                    $value = array((string) $value);
                }
                $lower = \strtolower($name);
                if (isset($this->headerNamesLowerCase[$lower])) {
                    $value = \array_merge($this->headers[$this->headerNamesLowerCase[$lower]], $value);
                    unset($this->headers[$this->headerNamesLowerCase[$lower]]);
                }
                $this->headers[$name] = $value;
                $this->headerNamesLowerCase[$lower] = $name;
            }
        }
        $this->protocolVersion = (string) $protocolVersion;
        $this->body = $body;
    }
    public function getProtocolVersion()
    {
        return $this->protocolVersion;
    }
    public function withProtocolVersion($version)
    {
        if ((string) $version === $this->protocolVersion) {
            return $this;
        }
        $message = clone $this;
        $message->protocolVersion = (string) $version;
        return $message;
    }
    public function getHeaders()
    {
        return $this->headers;
    }
    public function hasHeader($name)
    {
        return isset($this->headerNamesLowerCase[\strtolower($name)]);
    }
    public function getHeader($name)
    {
        $lower = \strtolower($name);
        return isset($this->headerNamesLowerCase[$lower]) ? $this->headers[$this->headerNamesLowerCase[$lower]] : array();
    }
    public function getHeaderLine($name)
    {
        return \implode(', ', $this->getHeader($name));
    }
    public function withHeader($name, $value)
    {
        if ($value === array()) {
            return $this->withoutHeader($name);
        } elseif (\is_array($value)) {
            foreach ($value as &$one) {
                $one = (string) $one;
            }
        } else {
            $value = array((string) $value);
        }
        $lower = \strtolower($name);
        if (isset($this->headerNamesLowerCase[$lower]) && $this->headerNamesLowerCase[$lower] === (string) $name && $this->headers[$this->headerNamesLowerCase[$lower]] === $value) {
            return $this;
        }
        $message = clone $this;
        if (isset($message->headerNamesLowerCase[$lower])) {
            unset($message->headers[$message->headerNamesLowerCase[$lower]]);
        }
        $message->headers[$name] = $value;
        $message->headerNamesLowerCase[$lower] = $name;
        return $message;
    }
    public function withAddedHeader($name, $value)
    {
        if ($value === array()) {
            return $this;
        }
        return $this->withHeader($name, \array_merge($this->getHeader($name), \is_array($value) ? $value : array($value)));
    }
    public function withoutHeader($name)
    {
        $lower = \strtolower($name);
        if (!isset($this->headerNamesLowerCase[$lower])) {
            return $this;
        }
        $message = clone $this;
        unset($message->headers[$message->headerNamesLowerCase[$lower]], $message->headerNamesLowerCase[$lower]);
        return $message;
    }
    public function getBody()
    {
        return $this->body;
    }
    public function withBody(StreamInterface $body)
    {
        if ($body === $this->body) {
            return $this;
        }
        $message = clone $this;
        $message->body = $body;
        return $message;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Io;

use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\RequestInterface;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\StreamInterface;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\UriInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Message\Uri;
/**
 * [Internal] Abstract HTTP request base class (PSR-7)
 *
 * @internal
 * @see RequestInterface
 */
abstract class AbstractRequest extends AbstractMessage implements RequestInterface
{
    /** @var ?string */
    private $requestTarget;
    /** @var string */
    private $method;
    /** @var UriInterface */
    private $uri;
    /**
     * @param string $method
     * @param string|UriInterface $uri
     * @param array<string,string|string[]> $headers
     * @param StreamInterface $body
     * @param string unknown $protocolVersion
     */
    protected function __construct($method, $uri, array $headers, StreamInterface $body, $protocolVersion)
    {
        if (\is_string($uri)) {
            $uri = new Uri($uri);
        } elseif (!$uri instanceof UriInterface) {
            throw new \InvalidArgumentException('Argument #2 ($uri) expected string|Psr\Http\Message\UriInterface');
        }
        // assign default `Host` request header from URI unless already given explicitly
        $host = $uri->getHost();
        if ($host !== '') {
            foreach ($headers as $name => $value) {
                if (\strtolower($name) === 'host' && $value !== array()) {
                    $host = '';
                    break;
                }
            }
            if ($host !== '') {
                $port = $uri->getPort();
                if ($port !== null && (!($port === 80 && $uri->getScheme() === 'http') || !($port === 443 && $uri->getScheme() === 'https'))) {
                    $host .= ':' . $port;
                }
                $headers = array('Host' => $host) + $headers;
            }
        }
        parent::__construct($protocolVersion, $headers, $body);
        $this->method = $method;
        $this->uri = $uri;
    }
    public function getRequestTarget()
    {
        if ($this->requestTarget !== null) {
            return $this->requestTarget;
        }
        $target = $this->uri->getPath();
        if ($target === '') {
            $target = '/';
        }
        if (($query = $this->uri->getQuery()) !== '') {
            $target .= '?' . $query;
        }
        return $target;
    }
    public function withRequestTarget($requestTarget)
    {
        if ((string) $requestTarget === $this->requestTarget) {
            return $this;
        }
        $request = clone $this;
        $request->requestTarget = (string) $requestTarget;
        return $request;
    }
    public function getMethod()
    {
        return $this->method;
    }
    public function withMethod($method)
    {
        if ((string) $method === $this->method) {
            return $this;
        }
        $request = clone $this;
        $request->method = (string) $method;
        return $request;
    }
    public function getUri()
    {
        return $this->uri;
    }
    public function withUri(UriInterface $uri, $preserveHost = \false)
    {
        if ($uri === $this->uri) {
            return $this;
        }
        $request = clone $this;
        $request->uri = $uri;
        $host = $uri->getHost();
        $port = $uri->getPort();
        if ($port !== null && $host !== '' && (!($port === 80 && $uri->getScheme() === 'http') || !($port === 443 && $uri->getScheme() === 'https'))) {
            $host .= ':' . $port;
        }
        // update `Host` request header if URI contains a new host and `$preserveHost` is false
        if ($host !== '' && (!$preserveHost || $request->getHeaderLine('Host') === '')) {
            // first remove all headers before assigning `Host` header to ensure it always comes first
            foreach (\array_keys($request->getHeaders()) as $name) {
                $request = $request->withoutHeader($name);
            }
            // add `Host` header first, then all other original headers
            $request = $request->withHeader('Host', $host);
            foreach ($this->withoutHeader('Host')->getHeaders() as $name => $value) {
                $request = $request->withHeader($name, $value);
            }
        }
        return $request;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Io;

use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\StreamInterface;
/**
 * [Internal] PSR-7 message body implementation using an in-memory buffer
 *
 * @internal
 */
class BufferedBody implements StreamInterface
{
    private $buffer = '';
    private $position = 0;
    private $closed = \false;
    /**
     * @param string $buffer
     */
    public function __construct($buffer)
    {
        $this->buffer = $buffer;
    }
    public function __toString()
    {
        if ($this->closed) {
            return '';
        }
        $this->seek(0);
        return $this->getContents();
    }
    public function close()
    {
        $this->buffer = '';
        $this->position = 0;
        $this->closed = \true;
    }
    public function detach()
    {
        $this->close();
        return null;
    }
    public function getSize()
    {
        return $this->closed ? null : \strlen($this->buffer);
    }
    public function tell()
    {
        if ($this->closed) {
            throw new \RuntimeException('Unable to tell position of closed stream');
        }
        return $this->position;
    }
    public function eof()
    {
        return $this->position >= \strlen($this->buffer);
    }
    public function isSeekable()
    {
        return !$this->closed;
    }
    public function seek($offset, $whence = \SEEK_SET)
    {
        if ($this->closed) {
            throw new \RuntimeException('Unable to seek on closed stream');
        }
        $old = $this->position;
        if ($whence === \SEEK_SET) {
            $this->position = $offset;
        } elseif ($whence === \SEEK_CUR) {
            $this->position += $offset;
        } elseif ($whence === \SEEK_END) {
            $this->position = \strlen($this->buffer) + $offset;
        } else {
            throw new \InvalidArgumentException('Invalid seek mode given');
        }
        if (!\is_int($this->position) || $this->position < 0) {
            $this->position = $old;
            throw new \RuntimeException('Unable to seek to position');
        }
    }
    public function rewind()
    {
        $this->seek(0);
    }
    public function isWritable()
    {
        return !$this->closed;
    }
    public function write($string)
    {
        if ($this->closed) {
            throw new \RuntimeException('Unable to write to closed stream');
        }
        if ($string === '') {
            return 0;
        }
        if ($this->position > 0 && !isset($this->buffer[$this->position - 1])) {
            $this->buffer = \str_pad($this->buffer, $this->position, "\x00");
        }
        $len = \strlen($string);
        $this->buffer = \substr($this->buffer, 0, $this->position) . $string . \substr($this->buffer, $this->position + $len);
        $this->position += $len;
        return $len;
    }
    public function isReadable()
    {
        return !$this->closed;
    }
    public function read($length)
    {
        if ($this->closed) {
            throw new \RuntimeException('Unable to read from closed stream');
        }
        if ($length < 1) {
            throw new \InvalidArgumentException('Invalid read length given');
        }
        if ($this->position + $length > \strlen($this->buffer)) {
            $length = \strlen($this->buffer) - $this->position;
        }
        if (!isset($this->buffer[$this->position])) {
            return '';
        }
        $pos = $this->position;
        $this->position += $length;
        return \substr($this->buffer, $pos, $length);
    }
    public function getContents()
    {
        if ($this->closed) {
            throw new \RuntimeException('Unable to read from closed stream');
        }
        if (!isset($this->buffer[$this->position])) {
            return '';
        }
        $pos = $this->position;
        $this->position = \strlen($this->buffer);
        return \substr($this->buffer, $pos);
    }
    public function getMetadata($key = null)
    {
        return $key === null ? array() : null;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Io;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\ReadableStreamInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\Util;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\WritableStreamInterface;
use Exception;
/**
 * [Internal] Decodes "Transfer-Encoding: chunked" from given stream and returns only payload data.
 *
 * This is used internally to decode incoming requests with this encoding.
 *
 * @internal
 */
class ChunkedDecoder extends EventEmitter implements ReadableStreamInterface
{
    const CRLF = "\r\n";
    const MAX_CHUNK_HEADER_SIZE = 1024;
    private $closed = \false;
    private $input;
    private $buffer = '';
    private $chunkSize = 0;
    private $transferredSize = 0;
    private $headerCompleted = \false;
    public function __construct(ReadableStreamInterface $input)
    {
        $this->input = $input;
        $this->input->on('data', array($this, 'handleData'));
        $this->input->on('end', array($this, 'handleEnd'));
        $this->input->on('error', array($this, 'handleError'));
        $this->input->on('close', array($this, 'close'));
    }
    public function isReadable()
    {
        return !$this->closed && $this->input->isReadable();
    }
    public function pause()
    {
        $this->input->pause();
    }
    public function resume()
    {
        $this->input->resume();
    }
    public function pipe(WritableStreamInterface $dest, array $options = array())
    {
        Util::pipe($this, $dest, $options);
        return $dest;
    }
    public function close()
    {
        if ($this->closed) {
            return;
        }
        $this->buffer = '';
        $this->closed = \true;
        $this->input->close();
        $this->emit('close');
        $this->removeAllListeners();
    }
    /** @internal */
    public function handleEnd()
    {
        if (!$this->closed) {
            $this->handleError(new Exception('Unexpected end event'));
        }
    }
    /** @internal */
    public function handleError(Exception $e)
    {
        $this->emit('error', array($e));
        $this->close();
    }
    /** @internal */
    public function handleData($data)
    {
        $this->buffer .= $data;
        while ($this->buffer !== '') {
            if (!$this->headerCompleted) {
                $positionCrlf = \strpos($this->buffer, static::CRLF);
                if ($positionCrlf === \false) {
                    // Header shouldn't be bigger than 1024 bytes
                    if (isset($this->buffer[static::MAX_CHUNK_HEADER_SIZE])) {
                        $this->handleError(new Exception('Chunk header size inclusive extension bigger than' . static::MAX_CHUNK_HEADER_SIZE . ' bytes'));
                    }
                    return;
                }
                $header = \strtolower((string) \substr($this->buffer, 0, $positionCrlf));
                $hexValue = $header;
                if (\strpos($header, ';') !== \false) {
                    $array = \explode(';', $header);
                    $hexValue = $array[0];
                }
                if ($hexValue !== '') {
                    $hexValue = \ltrim(\trim($hexValue), "0");
                    if ($hexValue === '') {
                        $hexValue = "0";
                    }
                }
                $this->chunkSize = @\hexdec($hexValue);
                if (!\is_int($this->chunkSize) || \dechex($this->chunkSize) !== $hexValue) {
                    $this->handleError(new Exception($hexValue . ' is not a valid hexadecimal number'));
                    return;
                }
                $this->buffer = (string) \substr($this->buffer, $positionCrlf + 2);
                $this->headerCompleted = \true;
                if ($this->buffer === '') {
                    return;
                }
            }
            $chunk = (string) \substr($this->buffer, 0, $this->chunkSize - $this->transferredSize);
            if ($chunk !== '') {
                $this->transferredSize += \strlen($chunk);
                $this->emit('data', array($chunk));
                $this->buffer = (string) \substr($this->buffer, \strlen($chunk));
            }
            $positionCrlf = \strpos($this->buffer, static::CRLF);
            if ($positionCrlf === 0) {
                if ($this->chunkSize === 0) {
                    $this->emit('end');
                    $this->close();
                    return;
                }
                $this->chunkSize = 0;
                $this->headerCompleted = \false;
                $this->transferredSize = 0;
                $this->buffer = (string) \substr($this->buffer, 2);
            } elseif ($this->chunkSize === 0) {
                // end chunk received, skip all trailer data
                $this->buffer = (string) \substr($this->buffer, $positionCrlf);
            }
            if ($positionCrlf !== 0 && $this->chunkSize !== 0 && $this->chunkSize === $this->transferredSize && \strlen($this->buffer) > 2) {
                // the first 2 characters are not CRLF, send error event
                $this->handleError(new Exception('Chunk does not end with a CRLF'));
                return;
            }
            if ($positionCrlf !== 0 && \strlen($this->buffer) < 2) {
                // No CRLF found, wait for additional data which could be a CRLF
                return;
            }
        }
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Io;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\ReadableStreamInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\Util;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\WritableStreamInterface;
/**
 * [Internal] Encodes given payload stream with "Transfer-Encoding: chunked" and emits encoded data
 *
 * This is used internally to encode outgoing requests with this encoding.
 *
 * @internal
 */
class ChunkedEncoder extends EventEmitter implements ReadableStreamInterface
{
    private $input;
    private $closed = \false;
    public function __construct(ReadableStreamInterface $input)
    {
        $this->input = $input;
        $this->input->on('data', array($this, 'handleData'));
        $this->input->on('end', array($this, 'handleEnd'));
        $this->input->on('error', array($this, 'handleError'));
        $this->input->on('close', array($this, 'close'));
    }
    public function isReadable()
    {
        return !$this->closed && $this->input->isReadable();
    }
    public function pause()
    {
        $this->input->pause();
    }
    public function resume()
    {
        $this->input->resume();
    }
    public function pipe(WritableStreamInterface $dest, array $options = array())
    {
        return Util::pipe($this, $dest, $options);
    }
    public function close()
    {
        if ($this->closed) {
            return;
        }
        $this->closed = \true;
        $this->input->close();
        $this->emit('close');
        $this->removeAllListeners();
    }
    /** @internal */
    public function handleData($data)
    {
        if ($data !== '') {
            $this->emit('data', array(\dechex(\strlen($data)) . "\r\n" . $data . "\r\n"));
        }
    }
    /** @internal */
    public function handleError(\Exception $e)
    {
        $this->emit('error', array($e));
        $this->close();
    }
    /** @internal */
    public function handleEnd()
    {
        $this->emit('data', array("0\r\n\r\n"));
        if (!$this->closed) {
            $this->emit('end');
            $this->close();
        }
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Io;

use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\UriInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\TimerInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\PromiseInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Socket\ConnectionInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Socket\ConnectorInterface;
/**
 * [Internal] Manages outgoing HTTP connections for the HTTP client
 *
 * @internal
 * @final
 */
class ClientConnectionManager
{
    /** @var ConnectorInterface */
    private $connector;
    /** @var LoopInterface */
    private $loop;
    /** @var string[] */
    private $idleUris = array();
    /** @var ConnectionInterface[] */
    private $idleConnections = array();
    /** @var TimerInterface[] */
    private $idleTimers = array();
    /** @var \Closure[] */
    private $idleStreamHandlers = array();
    /** @var float */
    private $maximumTimeToKeepAliveIdleConnection = 0.001;
    public function __construct(ConnectorInterface $connector, LoopInterface $loop)
    {
        $this->connector = $connector;
        $this->loop = $loop;
    }
    /**
     * @return PromiseInterface<ConnectionInterface>
     */
    public function connect(UriInterface $uri)
    {
        $scheme = $uri->getScheme();
        if ($scheme !== 'https' && $scheme !== 'http') {
            return \NightwatchAgent_kden27khxA4QoEfj\React\Promise\reject(new \InvalidArgumentException('Invalid request URL given'));
        }
        $port = $uri->getPort();
        if ($port === null) {
            $port = $scheme === 'https' ? 443 : 80;
        }
        $uri = ($scheme === 'https' ? 'tls://' : '') . $uri->getHost() . ':' . $port;
        // Reuse idle connection for same URI if available
        foreach ($this->idleConnections as $id => $connection) {
            if ($this->idleUris[$id] === $uri) {
                assert($this->idleStreamHandlers[$id] instanceof \Closure);
                $connection->removeListener('close', $this->idleStreamHandlers[$id]);
                $connection->removeListener('data', $this->idleStreamHandlers[$id]);
                $connection->removeListener('error', $this->idleStreamHandlers[$id]);
                assert($this->idleTimers[$id] instanceof TimerInterface);
                $this->loop->cancelTimer($this->idleTimers[$id]);
                unset($this->idleUris[$id], $this->idleConnections[$id], $this->idleTimers[$id], $this->idleStreamHandlers[$id]);
                return \NightwatchAgent_kden27khxA4QoEfj\React\Promise\resolve($connection);
            }
        }
        // Create new connection if no idle connection to same URI is available
        return $this->connector->connect($uri);
    }
    /**
     * Hands back an idle connection to the connection manager for possible future reuse.
     *
     * @return void
     */
    public function keepAlive(UriInterface $uri, ConnectionInterface $connection)
    {
        $scheme = $uri->getScheme();
        assert($scheme === 'https' || $scheme === 'http');
        $port = $uri->getPort();
        if ($port === null) {
            $port = $scheme === 'https' ? 443 : 80;
        }
        $this->idleUris[] = ($scheme === 'https' ? 'tls://' : '') . $uri->getHost() . ':' . $port;
        $this->idleConnections[] = $connection;
        $that = $this;
        $cleanUp = function () use ($connection, $that) {
            // call public method to support legacy PHP 5.3
            $that->cleanUpConnection($connection);
        };
        // clean up and close connection when maximum time to keep-alive idle connection has passed
        $this->idleTimers[] = $this->loop->addTimer($this->maximumTimeToKeepAliveIdleConnection, $cleanUp);
        // clean up and close connection when unexpected close/data/error event happens during idle time
        $this->idleStreamHandlers[] = $cleanUp;
        $connection->on('close', $cleanUp);
        $connection->on('data', $cleanUp);
        $connection->on('error', $cleanUp);
    }
    /**
     * @internal
     * @return void
     */
    public function cleanUpConnection(ConnectionInterface $connection)
    {
        $id = \array_search($connection, $this->idleConnections, \true);
        if ($id === \false) {
            return;
        }
        assert(\is_int($id));
        assert($this->idleTimers[$id] instanceof TimerInterface);
        $this->loop->cancelTimer($this->idleTimers[$id]);
        unset($this->idleUris[$id], $this->idleConnections[$id], $this->idleTimers[$id], $this->idleStreamHandlers[$id]);
        $connection->close();
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Io;

/** @internal */
class ClientRequestState
{
    /** @var int */
    public $numRequests = 0;
    /** @var ?\React\Promise\PromiseInterface */
    public $pending = null;
    /** @var ?\React\EventLoop\TimerInterface */
    public $timeout = null;
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Io;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\MessageInterface;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\RequestInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Message\Response;
use NightwatchAgent_kden27khxA4QoEfj\React\Socket\ConnectionInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\WritableStreamInterface;
/**
 * @event response
 * @event drain
 * @event error
 * @event close
 * @internal
 */
class ClientRequestStream extends EventEmitter implements WritableStreamInterface
{
    const STATE_INIT = 0;
    const STATE_WRITING_HEAD = 1;
    const STATE_HEAD_WRITTEN = 2;
    const STATE_END = 3;
    /** @var ClientConnectionManager */
    private $connectionManager;
    /** @var RequestInterface */
    private $request;
    /** @var ?ConnectionInterface */
    private $connection;
    /** @var string */
    private $buffer = '';
    private $responseFactory;
    private $state = self::STATE_INIT;
    private $ended = \false;
    private $pendingWrites = '';
    public function __construct(ClientConnectionManager $connectionManager, RequestInterface $request)
    {
        $this->connectionManager = $connectionManager;
        $this->request = $request;
    }
    public function isWritable()
    {
        return self::STATE_END > $this->state && !$this->ended;
    }
    private function writeHead()
    {
        $this->state = self::STATE_WRITING_HEAD;
        $expected = 0;
        $headers = "{$this->request->getMethod()} {$this->request->getRequestTarget()} HTTP/{$this->request->getProtocolVersion()}\r\n";
        foreach ($this->request->getHeaders() as $name => $values) {
            if (\strpos($name, ':') !== \false) {
                $expected = -1;
                break;
            }
            foreach ($values as $value) {
                $headers .= "{$name}: {$value}\r\n";
                ++$expected;
            }
        }
        /** @var array $m legacy PHP 5.3 only */
        if (!\preg_match('#^\S+ \S+ HTTP/1\.[01]\r\n#m', $headers) || \substr_count($headers, "\n") !== $expected + 1 || (\PHP_VERSION_ID >= 50400 ? \preg_match_all(AbstractMessage::REGEX_HEADERS, $headers) : \preg_match_all(AbstractMessage::REGEX_HEADERS, $headers, $m)) !== $expected) {
            $this->closeError(new \InvalidArgumentException('Unable to send request with invalid request headers'));
            return;
        }
        $connectionRef =& $this->connection;
        $stateRef =& $this->state;
        $pendingWrites =& $this->pendingWrites;
        $that = $this;
        $promise = $this->connectionManager->connect($this->request->getUri());
        $promise->then(function (ConnectionInterface $connection) use ($headers, &$connectionRef, &$stateRef, &$pendingWrites, $that) {
            $connectionRef = $connection;
            assert($connectionRef instanceof ConnectionInterface);
            $connection->on('drain', array($that, 'handleDrain'));
            $connection->on('data', array($that, 'handleData'));
            $connection->on('end', array($that, 'handleEnd'));
            $connection->on('error', array($that, 'handleError'));
            $connection->on('close', array($that, 'close'));
            $more = $connection->write($headers . "\r\n" . $pendingWrites);
            assert($stateRef === ClientRequestStream::STATE_WRITING_HEAD);
            $stateRef = ClientRequestStream::STATE_HEAD_WRITTEN;
            // clear pending writes if non-empty
            if ($pendingWrites !== '') {
                $pendingWrites = '';
                if ($more) {
                    $that->emit('drain');
                }
            }
        }, array($this, 'closeError'));
        $this->on('close', function () use ($promise) {
            $promise->cancel();
        });
    }
    public function write($data)
    {
        if (!$this->isWritable()) {
            return \false;
        }
        // write directly to connection stream if already available
        if (self::STATE_HEAD_WRITTEN <= $this->state) {
            return $this->connection->write($data);
        }
        // otherwise buffer and try to establish connection
        $this->pendingWrites .= $data;
        if (self::STATE_WRITING_HEAD > $this->state) {
            $this->writeHead();
        }
        return \false;
    }
    public function end($data = null)
    {
        if (!$this->isWritable()) {
            return;
        }
        if (null !== $data) {
            $this->write($data);
        } else if (self::STATE_WRITING_HEAD > $this->state) {
            $this->writeHead();
        }
        $this->ended = \true;
    }
    /** @internal */
    public function handleDrain()
    {
        $this->emit('drain');
    }
    /** @internal */
    public function handleData($data)
    {
        $this->buffer .= $data;
        // buffer until double CRLF (or double LF for compatibility with legacy servers)
        $eom = \strpos($this->buffer, "\r\n\r\n");
        $eomLegacy = \strpos($this->buffer, "\n\n");
        if ($eom !== \false || $eomLegacy !== \false) {
            try {
                if ($eom !== \false && ($eomLegacy === \false || $eom < $eomLegacy)) {
                    $response = Response::parseMessage(\substr($this->buffer, 0, $eom + 2));
                    $bodyChunk = (string) \substr($this->buffer, $eom + 4);
                } else {
                    $response = Response::parseMessage(\substr($this->buffer, 0, $eomLegacy + 1));
                    $bodyChunk = (string) \substr($this->buffer, $eomLegacy + 2);
                }
            } catch (\InvalidArgumentException $exception) {
                $this->closeError($exception);
                return;
            }
            // response headers successfully received => remove listeners for connection events
            $connection = $this->connection;
            assert($connection instanceof ConnectionInterface);
            $connection->removeListener('drain', array($this, 'handleDrain'));
            $connection->removeListener('data', array($this, 'handleData'));
            $connection->removeListener('end', array($this, 'handleEnd'));
            $connection->removeListener('error', array($this, 'handleError'));
            $connection->removeListener('close', array($this, 'close'));
            $this->connection = null;
            $this->buffer = '';
            // take control over connection handling and check if we can reuse the connection once response body closes
            $that = $this;
            $request = $this->request;
            $connectionManager = $this->connectionManager;
            $successfulEndReceived = \false;
            $input = $body = new CloseProtectionStream($connection);
            $input->on('close', function () use ($connection, $that, $connectionManager, $request, $response, &$successfulEndReceived) {
                // only reuse connection after successful response and both request and response allow keep alive
                if ($successfulEndReceived && $connection->isReadable() && $that->hasMessageKeepAliveEnabled($response) && $that->hasMessageKeepAliveEnabled($request)) {
                    $connectionManager->keepAlive($request->getUri(), $connection);
                } else {
                    $connection->close();
                }
                $that->close();
            });
            // determine length of response body
            $length = null;
            $code = $response->getStatusCode();
            if ($this->request->getMethod() === 'HEAD' || $code >= 100 && $code < 200 || $code == Response::STATUS_NO_CONTENT || $code == Response::STATUS_NOT_MODIFIED) {
                $length = 0;
            } elseif (\strtolower($response->getHeaderLine('Transfer-Encoding')) === 'chunked') {
                $body = new ChunkedDecoder($body);
            } elseif ($response->hasHeader('Content-Length')) {
                $length = (int) $response->getHeaderLine('Content-Length');
            }
            $response = $response->withBody($body = new ReadableBodyStream($body, $length));
            $body->on('end', function () use (&$successfulEndReceived) {
                $successfulEndReceived = \true;
            });
            // emit response with streaming response body (see `Sender`)
            $this->emit('response', array($response, $body));
            // re-emit HTTP response body to trigger body parsing if parts of it are buffered
            if ($bodyChunk !== '') {
                $input->handleData($bodyChunk);
            } elseif ($length === 0) {
                $input->handleEnd();
            }
        }
    }
    /** @internal */
    public function handleEnd()
    {
        $this->closeError(new \RuntimeException("Connection ended before receiving response"));
    }
    /** @internal */
    public function handleError(\Exception $error)
    {
        $this->closeError(new \RuntimeException("An error occurred in the underlying stream", 0, $error));
    }
    /** @internal */
    public function closeError(\Exception $error)
    {
        if (self::STATE_END <= $this->state) {
            return;
        }
        $this->emit('error', array($error));
        $this->close();
    }
    public function close()
    {
        if (self::STATE_END <= $this->state) {
            return;
        }
        $this->state = self::STATE_END;
        $this->pendingWrites = '';
        $this->buffer = '';
        if ($this->connection instanceof ConnectionInterface) {
            $this->connection->close();
            $this->connection = null;
        }
        $this->emit('close');
        $this->removeAllListeners();
    }
    /**
     * @internal
     * @return bool
     * @link https://www.rfc-editor.org/rfc/rfc9112#section-9.3
     * @link https://www.rfc-editor.org/rfc/rfc7230#section-6.1
     */
    public function hasMessageKeepAliveEnabled(MessageInterface $message)
    {
        // @link https://www.rfc-editor.org/rfc/rfc9110#section-7.6.1
        $connectionOptions = \array_map('trim', \explode(',', \strtolower($message->getHeaderLine('Connection'))));
        if (\in_array('close', $connectionOptions, \true)) {
            return \false;
        }
        if ($message->getProtocolVersion() === '1.1') {
            return \true;
        }
        if (\in_array('keep-alive', $connectionOptions, \true)) {
            return \true;
        }
        return \false;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Io;

use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
/**
 * [internal] Clock source that returns current timestamp and memoize clock for same tick
 *
 * This is mostly used as an internal optimization to avoid unneeded syscalls to
 * get the current system time multiple times within the same loop tick. For the
 * purpose of the HTTP server, the clock is assumed to not change to a
 * significant degree within the same loop tick. If you need a high precision
 * clock source, you may want to use `\hrtime()` instead (PHP 7.3+).
 *
 * The API is modelled to resemble the PSR-20 `ClockInterface` (in draft at the
 * time of writing this), but uses a `float` return value for performance
 * reasons instead.
 *
 * Note that this is an internal class only and nothing you should usually care
 * about for outside use.
 *
 * @internal
 */
class Clock
{
    /** @var LoopInterface $loop */
    private $loop;
    /** @var ?float */
    private $now;
    public function __construct(LoopInterface $loop)
    {
        $this->loop = $loop;
    }
    /** @return float */
    public function now()
    {
        if ($this->now === null) {
            $this->now = \microtime(\true);
            // remember clock for current loop tick only and update on next tick
            $now =& $this->now;
            $this->loop->futureTick(function () use (&$now) {
                assert($now !== null);
                $now = null;
            });
        }
        return $this->now;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Io;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\ReadableStreamInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\Util;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\WritableStreamInterface;
/**
 * [Internal] Protects a given stream from actually closing and only discards its incoming data instead.
 *
 * This is used internally to prevent the underlying connection from closing, so
 * that we can still send back a response over the same stream.
 *
 * @internal
 * */
class CloseProtectionStream extends EventEmitter implements ReadableStreamInterface
{
    private $input;
    private $closed = \false;
    private $paused = \false;
    /**
     * @param ReadableStreamInterface $input stream that will be discarded instead of closing it on an 'close' event.
     */
    public function __construct(ReadableStreamInterface $input)
    {
        $this->input = $input;
        $this->input->on('data', array($this, 'handleData'));
        $this->input->on('end', array($this, 'handleEnd'));
        $this->input->on('error', array($this, 'handleError'));
        $this->input->on('close', array($this, 'close'));
    }
    public function isReadable()
    {
        return !$this->closed && $this->input->isReadable();
    }
    public function pause()
    {
        if ($this->closed) {
            return;
        }
        $this->paused = \true;
        $this->input->pause();
    }
    public function resume()
    {
        if ($this->closed) {
            return;
        }
        $this->paused = \false;
        $this->input->resume();
    }
    public function pipe(WritableStreamInterface $dest, array $options = array())
    {
        Util::pipe($this, $dest, $options);
        return $dest;
    }
    public function close()
    {
        if ($this->closed) {
            return;
        }
        $this->closed = \true;
        // stop listening for incoming events
        $this->input->removeListener('data', array($this, 'handleData'));
        $this->input->removeListener('error', array($this, 'handleError'));
        $this->input->removeListener('end', array($this, 'handleEnd'));
        $this->input->removeListener('close', array($this, 'close'));
        // resume the stream to ensure we discard everything from incoming connection
        if ($this->paused) {
            $this->paused = \false;
            $this->input->resume();
        }
        $this->emit('close');
        $this->removeAllListeners();
    }
    /** @internal */
    public function handleData($data)
    {
        $this->emit('data', array($data));
    }
    /** @internal */
    public function handleEnd()
    {
        $this->emit('end');
        $this->close();
    }
    /** @internal */
    public function handleError(\Exception $e)
    {
        $this->emit('error', array($e));
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Io;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\StreamInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\ReadableStreamInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\Util;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\WritableStreamInterface;
/**
 * [Internal] Bridge between an empty StreamInterface from PSR-7 and ReadableStreamInterface from ReactPHP
 *
 * This class is used in the server to represent an empty body stream of an
 * incoming response from the client. This is similar to the `HttpBodyStream`,
 * but is specifically designed for the common case of having an empty message
 * body.
 *
 * Note that this is an internal class only and nothing you should usually care
 * about. See the `StreamInterface` and `ReadableStreamInterface` for more
 * details.
 *
 * @see HttpBodyStream
 * @see StreamInterface
 * @see ReadableStreamInterface
 * @internal
 */
class EmptyBodyStream extends EventEmitter implements StreamInterface, ReadableStreamInterface
{
    private $closed = \false;
    public function isReadable()
    {
        return !$this->closed;
    }
    public function pause()
    {
        // NOOP
    }
    public function resume()
    {
        // NOOP
    }
    public function pipe(WritableStreamInterface $dest, array $options = array())
    {
        Util::pipe($this, $dest, $options);
        return $dest;
    }
    public function close()
    {
        if ($this->closed) {
            return;
        }
        $this->closed = \true;
        $this->emit('close');
        $this->removeAllListeners();
    }
    public function getSize()
    {
        return 0;
    }
    /** @ignore */
    public function __toString()
    {
        return '';
    }
    /** @ignore */
    public function detach()
    {
        return null;
    }
    /** @ignore */
    public function tell()
    {
        throw new \BadMethodCallException();
    }
    /** @ignore */
    public function eof()
    {
        throw new \BadMethodCallException();
    }
    /** @ignore */
    public function isSeekable()
    {
        return \false;
    }
    /** @ignore */
    public function seek($offset, $whence = \SEEK_SET)
    {
        throw new \BadMethodCallException();
    }
    /** @ignore */
    public function rewind()
    {
        throw new \BadMethodCallException();
    }
    /** @ignore */
    public function isWritable()
    {
        return \false;
    }
    /** @ignore */
    public function write($string)
    {
        throw new \BadMethodCallException();
    }
    /** @ignore */
    public function read($length)
    {
        throw new \BadMethodCallException();
    }
    /** @ignore */
    public function getContents()
    {
        return '';
    }
    /** @ignore */
    public function getMetadata($key = null)
    {
        return $key === null ? array() : null;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Io;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\StreamInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\ReadableStreamInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\Util;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\WritableStreamInterface;
/**
 * [Internal] Bridge between StreamInterface from PSR-7 and ReadableStreamInterface from ReactPHP
 *
 * This class is used in the server to stream the body of an incoming response
 * from the client. This allows us to stream big amounts of data without having
 * to buffer this data. Similarly, this used to stream the body of an outgoing
 * request body to the client. The data will be sent directly to the client.
 *
 * Note that this is an internal class only and nothing you should usually care
 * about. See the `StreamInterface` and `ReadableStreamInterface` for more
 * details.
 *
 * @see StreamInterface
 * @see ReadableStreamInterface
 * @internal
 */
class HttpBodyStream extends EventEmitter implements StreamInterface, ReadableStreamInterface
{
    public $input;
    private $closed = \false;
    private $size;
    /**
     * @param ReadableStreamInterface $input Stream data from $stream as a body of a PSR-7 object4
     * @param int|null $size size of the data body
     */
    public function __construct(ReadableStreamInterface $input, $size)
    {
        $this->input = $input;
        $this->size = $size;
        $this->input->on('data', array($this, 'handleData'));
        $this->input->on('end', array($this, 'handleEnd'));
        $this->input->on('error', array($this, 'handleError'));
        $this->input->on('close', array($this, 'close'));
    }
    public function isReadable()
    {
        return !$this->closed && $this->input->isReadable();
    }
    public function pause()
    {
        $this->input->pause();
    }
    public function resume()
    {
        $this->input->resume();
    }
    public function pipe(WritableStreamInterface $dest, array $options = array())
    {
        Util::pipe($this, $dest, $options);
        return $dest;
    }
    public function close()
    {
        if ($this->closed) {
            return;
        }
        $this->closed = \true;
        $this->input->close();
        $this->emit('close');
        $this->removeAllListeners();
    }
    public function getSize()
    {
        return $this->size;
    }
    /** @ignore */
    public function __toString()
    {
        return '';
    }
    /** @ignore */
    public function detach()
    {
        return null;
    }
    /** @ignore */
    public function tell()
    {
        throw new \BadMethodCallException();
    }
    /** @ignore */
    public function eof()
    {
        throw new \BadMethodCallException();
    }
    /** @ignore */
    public function isSeekable()
    {
        return \false;
    }
    /** @ignore */
    public function seek($offset, $whence = \SEEK_SET)
    {
        throw new \BadMethodCallException();
    }
    /** @ignore */
    public function rewind()
    {
        throw new \BadMethodCallException();
    }
    /** @ignore */
    public function isWritable()
    {
        return \false;
    }
    /** @ignore */
    public function write($string)
    {
        throw new \BadMethodCallException();
    }
    /** @ignore */
    public function read($length)
    {
        throw new \BadMethodCallException();
    }
    /** @ignore */
    public function getContents()
    {
        return '';
    }
    /** @ignore */
    public function getMetadata($key = null)
    {
        return null;
    }
    /** @internal */
    public function handleData($data)
    {
        $this->emit('data', array($data));
    }
    /** @internal */
    public function handleError(\Exception $e)
    {
        $this->emit('error', array($e));
        $this->close();
    }
    /** @internal */
    public function handleEnd()
    {
        if (!$this->closed) {
            $this->emit('end');
            $this->close();
        }
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Io;

/**
 * @internal
 */
final class IniUtil
{
    /**
     * Convert a ini like size to a numeric size in bytes.
     *
     * @param string $size
     * @return int
     */
    public static function iniSizeToBytes($size)
    {
        if (\is_numeric($size)) {
            return (int) $size;
        }
        $suffix = \strtoupper(\substr($size, -1));
        $strippedSize = \substr($size, 0, -1);
        if (!\is_numeric($strippedSize)) {
            throw new \InvalidArgumentException("{$size} is not a valid ini size");
        }
        if ($strippedSize <= 0) {
            throw new \InvalidArgumentException("Expect {$size} to be higher isn't zero or lower");
        }
        if ($suffix === 'K') {
            return $strippedSize * 1024;
        }
        if ($suffix === 'M') {
            return $strippedSize * 1024 * 1024;
        }
        if ($suffix === 'G') {
            return $strippedSize * 1024 * 1024 * 1024;
        }
        if ($suffix === 'T') {
            return $strippedSize * 1024 * 1024 * 1024 * 1024;
        }
        return (int) $size;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Io;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\ReadableStreamInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\Util;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\WritableStreamInterface;
/**
 * [Internal] Limits the amount of data the given stream can emit
 *
 * This is used internally to limit the size of the underlying connection stream
 * to the size defined by the "Content-Length" header of the incoming request.
 *
 * @internal
 */
class LengthLimitedStream extends EventEmitter implements ReadableStreamInterface
{
    private $stream;
    private $closed = \false;
    private $transferredLength = 0;
    private $maxLength;
    public function __construct(ReadableStreamInterface $stream, $maxLength)
    {
        $this->stream = $stream;
        $this->maxLength = $maxLength;
        $this->stream->on('data', array($this, 'handleData'));
        $this->stream->on('end', array($this, 'handleEnd'));
        $this->stream->on('error', array($this, 'handleError'));
        $this->stream->on('close', array($this, 'close'));
    }
    public function isReadable()
    {
        return !$this->closed && $this->stream->isReadable();
    }
    public function pause()
    {
        $this->stream->pause();
    }
    public function resume()
    {
        $this->stream->resume();
    }
    public function pipe(WritableStreamInterface $dest, array $options = array())
    {
        Util::pipe($this, $dest, $options);
        return $dest;
    }
    public function close()
    {
        if ($this->closed) {
            return;
        }
        $this->closed = \true;
        $this->stream->close();
        $this->emit('close');
        $this->removeAllListeners();
    }
    /** @internal */
    public function handleData($data)
    {
        if ($this->transferredLength + \strlen($data) > $this->maxLength) {
            // Only emit data until the value of 'Content-Length' is reached, the rest will be ignored
            $data = (string) \substr($data, 0, $this->maxLength - $this->transferredLength);
        }
        if ($data !== '') {
            $this->transferredLength += \strlen($data);
            $this->emit('data', array($data));
        }
        if ($this->transferredLength === $this->maxLength) {
            // 'Content-Length' reached, stream will end
            $this->emit('end');
            $this->close();
            $this->stream->removeListener('data', array($this, 'handleData'));
        }
    }
    /** @internal */
    public function handleError(\Exception $e)
    {
        $this->emit('error', array($e));
        $this->close();
    }
    /** @internal */
    public function handleEnd()
    {
        if (!$this->closed) {
            $this->handleError(new \Exception('Unexpected end event'));
        }
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Io;

use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\ResponseInterface;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\ServerRequestInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\PromiseInterface;
/**
 * [Internal] Middleware runner to expose an array of middleware request handlers as a single request handler callable
 *
 * @internal
 */
final class MiddlewareRunner
{
    /**
     * @var callable[]
     */
    private $middleware;
    /**
     * @param callable[] $middleware
     */
    public function __construct(array $middleware)
    {
        $this->middleware = \array_values($middleware);
    }
    /**
     * @param ServerRequestInterface $request
     * @return ResponseInterface|PromiseInterface<ResponseInterface>
     * @throws \Exception
     */
    public function __invoke(ServerRequestInterface $request)
    {
        if (empty($this->middleware)) {
            throw new \RuntimeException('No middleware to run');
        }
        return $this->call($request, 0);
    }
    /** @internal */
    public function call(ServerRequestInterface $request, $position)
    {
        // final request handler will be invoked without a next handler
        if (!isset($this->middleware[$position + 1])) {
            $handler = $this->middleware[$position];
            return $handler($request);
        }
        $that = $this;
        $next = function (ServerRequestInterface $request) use ($that, $position) {
            return $that->call($request, $position + 1);
        };
        // invoke middleware request handler with next handler
        $handler = $this->middleware[$position];
        return $handler($request, $next);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Io;

use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\ServerRequestInterface;
/**
 * [Internal] Parses a string body with "Content-Type: multipart/form-data" into structured data
 *
 * This is use internally to parse incoming request bodies into structured data
 * that resembles PHP's `$_POST` and `$_FILES` superglobals.
 *
 * @internal
 * @link https://tools.ietf.org/html/rfc7578
 * @link https://tools.ietf.org/html/rfc2046#section-5.1.1
 */
final class MultipartParser
{
    /**
     * @var ServerRequestInterface|null
     */
    private $request;
    /**
     * @var int|null
     */
    private $maxFileSize;
    /**
     * Based on $maxInputVars and $maxFileUploads
     *
     * @var int
     */
    private $maxMultipartBodyParts;
    /**
     * ini setting "max_input_vars"
     *
     * Does not exist in PHP < 5.3.9 or HHVM, so assume PHP's default 1000 here.
     *
     * @var int
     * @link http://php.net/manual/en/info.configuration.php#ini.max-input-vars
     */
    private $maxInputVars = 1000;
    /**
     * ini setting "max_input_nesting_level"
     *
     * Does not exist in HHVM, but assumes hard coded to 64 (PHP's default).
     *
     * @var int
     * @link http://php.net/manual/en/info.configuration.php#ini.max-input-nesting-level
     */
    private $maxInputNestingLevel = 64;
    /**
     * ini setting "upload_max_filesize"
     *
     * @var int
     */
    private $uploadMaxFilesize;
    /**
     * ini setting "max_file_uploads"
     *
     * Additionally, setting "file_uploads = off" effectively sets this to zero.
     *
     * @var int
     */
    private $maxFileUploads;
    private $multipartBodyPartCount = 0;
    private $postCount = 0;
    private $filesCount = 0;
    private $emptyCount = 0;
    private $cursor = 0;
    /**
     * @param int|string|null $uploadMaxFilesize
     * @param int|null $maxFileUploads
     */
    public function __construct($uploadMaxFilesize = null, $maxFileUploads = null)
    {
        $var = \ini_get('max_input_vars');
        if ($var !== \false) {
            $this->maxInputVars = (int) $var;
        }
        $var = \ini_get('max_input_nesting_level');
        if ($var !== \false) {
            $this->maxInputNestingLevel = (int) $var;
        }
        if ($uploadMaxFilesize === null) {
            $uploadMaxFilesize = \ini_get('upload_max_filesize');
        }
        $this->uploadMaxFilesize = IniUtil::iniSizeToBytes($uploadMaxFilesize);
        $this->maxFileUploads = $maxFileUploads === null ? \ini_get('file_uploads') === '' ? 0 : (int) \ini_get('max_file_uploads') : (int) $maxFileUploads;
        $this->maxMultipartBodyParts = $this->maxInputVars + $this->maxFileUploads;
    }
    public function parse(ServerRequestInterface $request)
    {
        $contentType = $request->getHeaderLine('content-type');
        if (!\preg_match('/boundary="?(.*?)"?$/', $contentType, $matches)) {
            return $request;
        }
        $this->request = $request;
        $this->parseBody('--' . $matches[1], (string) $request->getBody());
        $request = $this->request;
        $this->request = null;
        $this->multipartBodyPartCount = 0;
        $this->cursor = 0;
        $this->postCount = 0;
        $this->filesCount = 0;
        $this->emptyCount = 0;
        $this->maxFileSize = null;
        return $request;
    }
    private function parseBody($boundary, $buffer)
    {
        $len = \strlen($boundary);
        // ignore everything before initial boundary (SHOULD be empty)
        $this->cursor = \strpos($buffer, $boundary . "\r\n");
        while ($this->cursor !== \false) {
            // search following boundary (preceded by newline)
            // ignore last if not followed by boundary (SHOULD end with "--")
            $this->cursor += $len + 2;
            $end = \strpos($buffer, "\r\n" . $boundary, $this->cursor);
            if ($end === \false) {
                break;
            }
            // parse one part and continue searching for next
            $this->parsePart(\substr($buffer, $this->cursor, $end - $this->cursor));
            $this->cursor = $end;
            if (++$this->multipartBodyPartCount > $this->maxMultipartBodyParts) {
                break;
            }
        }
    }
    private function parsePart($chunk)
    {
        $pos = \strpos($chunk, "\r\n\r\n");
        if ($pos === \false) {
            return;
        }
        $headers = $this->parseHeaders((string) substr($chunk, 0, $pos));
        $body = (string) \substr($chunk, $pos + 4);
        if (!isset($headers['content-disposition'])) {
            return;
        }
        $name = $this->getParameterFromHeader($headers['content-disposition'], 'name');
        if ($name === null) {
            return;
        }
        $filename = $this->getParameterFromHeader($headers['content-disposition'], 'filename');
        if ($filename !== null) {
            $this->parseFile($name, $filename, isset($headers['content-type'][0]) ? $headers['content-type'][0] : null, $body);
        } else {
            $this->parsePost($name, $body);
        }
    }
    private function parseFile($name, $filename, $contentType, $contents)
    {
        $file = $this->parseUploadedFile($filename, $contentType, $contents);
        if ($file === null) {
            return;
        }
        $this->request = $this->request->withUploadedFiles($this->extractPost($this->request->getUploadedFiles(), $name, $file));
    }
    private function parseUploadedFile($filename, $contentType, $contents)
    {
        $size = \strlen($contents);
        // no file selected (zero size and empty filename)
        if ($size === 0 && $filename === '') {
            // ignore excessive number of empty file uploads
            if (++$this->emptyCount + $this->filesCount > $this->maxInputVars) {
                return;
            }
            return new UploadedFile(new BufferedBody(''), $size, \UPLOAD_ERR_NO_FILE, $filename, $contentType);
        }
        // ignore excessive number of file uploads
        if (++$this->filesCount > $this->maxFileUploads) {
            return;
        }
        // file exceeds "upload_max_filesize" ini setting
        if ($size > $this->uploadMaxFilesize) {
            return new UploadedFile(new BufferedBody(''), $size, \UPLOAD_ERR_INI_SIZE, $filename, $contentType);
        }
        // file exceeds MAX_FILE_SIZE value
        if ($this->maxFileSize !== null && $size > $this->maxFileSize) {
            return new UploadedFile(new BufferedBody(''), $size, \UPLOAD_ERR_FORM_SIZE, $filename, $contentType);
        }
        return new UploadedFile(new BufferedBody($contents), $size, \UPLOAD_ERR_OK, $filename, $contentType);
    }
    private function parsePost($name, $value)
    {
        // ignore excessive number of post fields
        if (++$this->postCount > $this->maxInputVars) {
            return;
        }
        $this->request = $this->request->withParsedBody($this->extractPost($this->request->getParsedBody(), $name, $value));
        if (\strtoupper($name) === 'MAX_FILE_SIZE') {
            $this->maxFileSize = (int) $value;
            if ($this->maxFileSize === 0) {
                $this->maxFileSize = null;
            }
        }
    }
    private function parseHeaders($header)
    {
        $headers = array();
        foreach (\explode("\r\n", \trim($header)) as $line) {
            $parts = \explode(':', $line, 2);
            if (!isset($parts[1])) {
                continue;
            }
            $key = \strtolower(trim($parts[0]));
            $values = \explode(';', $parts[1]);
            $values = \array_map('trim', $values);
            $headers[$key] = $values;
        }
        return $headers;
    }
    private function getParameterFromHeader(array $header, $parameter)
    {
        foreach ($header as $part) {
            if (\preg_match('/' . $parameter . '="?(.*?)"?$/', $part, $matches)) {
                return $matches[1];
            }
        }
        return null;
    }
    private function extractPost($postFields, $key, $value)
    {
        $chunks = \explode('[', $key);
        if (\count($chunks) == 1) {
            $postFields[$key] = $value;
            return $postFields;
        }
        // ignore this key if maximum nesting level is exceeded
        if (isset($chunks[$this->maxInputNestingLevel])) {
            return $postFields;
        }
        $chunkKey = \rtrim($chunks[0], ']');
        $parent =& $postFields;
        for ($i = 1; isset($chunks[$i]); $i++) {
            $previousChunkKey = $chunkKey;
            if ($previousChunkKey === '') {
                $parent[] = array();
                \end($parent);
                $parent =& $parent[\key($parent)];
            } else {
                if (!isset($parent[$previousChunkKey]) || !\is_array($parent[$previousChunkKey])) {
                    $parent[$previousChunkKey] = array();
                }
                $parent =& $parent[$previousChunkKey];
            }
            $chunkKey = \rtrim($chunks[$i], ']');
        }
        if ($chunkKey === '') {
            $parent[] = $value;
        } else {
            $parent[$chunkKey] = $value;
        }
        return $postFields;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Io;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\ReadableStreamInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\Util;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\WritableStreamInterface;
/**
 * [Internal] Pauses a given stream and buffers all events while paused
 *
 * This class is used to buffer all events that happen on a given stream while
 * it is paused. This allows you to pause a stream and no longer watch for any
 * of its events. Once the stream is resumed, all buffered events will be
 * emitted. Explicitly closing the resulting stream clears all buffers.
 *
 * Note that this is an internal class only and nothing you should usually care
 * about.
 *
 * @see ReadableStreamInterface
 * @internal
 */
class PauseBufferStream extends EventEmitter implements ReadableStreamInterface
{
    private $input;
    private $closed = \false;
    private $paused = \false;
    private $dataPaused = '';
    private $endPaused = \false;
    private $closePaused = \false;
    private $errorPaused;
    private $implicit = \false;
    public function __construct(ReadableStreamInterface $input)
    {
        $this->input = $input;
        $this->input->on('data', array($this, 'handleData'));
        $this->input->on('end', array($this, 'handleEnd'));
        $this->input->on('error', array($this, 'handleError'));
        $this->input->on('close', array($this, 'handleClose'));
    }
    /**
     * pause and remember this was not explicitly from user control
     *
     * @internal
     */
    public function pauseImplicit()
    {
        $this->pause();
        $this->implicit = \true;
    }
    /**
     * resume only if this was previously paused implicitly and not explicitly from user control
     *
     * @internal
     */
    public function resumeImplicit()
    {
        if ($this->implicit) {
            $this->resume();
        }
    }
    public function isReadable()
    {
        return !$this->closed;
    }
    public function pause()
    {
        if ($this->closed) {
            return;
        }
        $this->input->pause();
        $this->paused = \true;
        $this->implicit = \false;
    }
    public function resume()
    {
        if ($this->closed) {
            return;
        }
        $this->paused = \false;
        $this->implicit = \false;
        if ($this->dataPaused !== '') {
            $this->emit('data', array($this->dataPaused));
            $this->dataPaused = '';
        }
        if ($this->errorPaused) {
            $this->emit('error', array($this->errorPaused));
            return $this->close();
        }
        if ($this->endPaused) {
            $this->endPaused = \false;
            $this->emit('end');
            return $this->close();
        }
        if ($this->closePaused) {
            $this->closePaused = \false;
            return $this->close();
        }
        $this->input->resume();
    }
    public function pipe(WritableStreamInterface $dest, array $options = array())
    {
        Util::pipe($this, $dest, $options);
        return $dest;
    }
    public function close()
    {
        if ($this->closed) {
            return;
        }
        $this->closed = \true;
        $this->dataPaused = '';
        $this->endPaused = $this->closePaused = \false;
        $this->errorPaused = null;
        $this->input->close();
        $this->emit('close');
        $this->removeAllListeners();
    }
    /** @internal */
    public function handleData($data)
    {
        if ($this->paused) {
            $this->dataPaused .= $data;
            return;
        }
        $this->emit('data', array($data));
    }
    /** @internal */
    public function handleError(\Exception $e)
    {
        if ($this->paused) {
            $this->errorPaused = $e;
            return;
        }
        $this->emit('error', array($e));
        $this->close();
    }
    /** @internal */
    public function handleEnd()
    {
        if ($this->paused) {
            $this->endPaused = \true;
            return;
        }
        if (!$this->closed) {
            $this->emit('end');
            $this->close();
        }
    }
    /** @internal */
    public function handleClose()
    {
        if ($this->paused) {
            $this->closePaused = \true;
            return;
        }
        $this->close();
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Io;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\StreamInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\ReadableStreamInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\Util;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\WritableStreamInterface;
/**
 * @internal
 */
class ReadableBodyStream extends EventEmitter implements ReadableStreamInterface, StreamInterface
{
    private $input;
    private $position = 0;
    private $size;
    private $closed = \false;
    public function __construct(ReadableStreamInterface $input, $size = null)
    {
        $this->input = $input;
        $this->size = $size;
        $that = $this;
        $pos =& $this->position;
        $input->on('data', function ($data) use ($that, &$pos, $size) {
            $that->emit('data', array($data));
            $pos += \strlen($data);
            if ($size !== null && $pos >= $size) {
                $that->handleEnd();
            }
        });
        $input->on('error', function ($error) use ($that) {
            $that->emit('error', array($error));
            $that->close();
        });
        $input->on('end', array($that, 'handleEnd'));
        $input->on('close', array($that, 'close'));
    }
    public function close()
    {
        if (!$this->closed) {
            $this->closed = \true;
            $this->input->close();
            $this->emit('close');
            $this->removeAllListeners();
        }
    }
    public function isReadable()
    {
        return $this->input->isReadable();
    }
    public function pause()
    {
        $this->input->pause();
    }
    public function resume()
    {
        $this->input->resume();
    }
    public function pipe(WritableStreamInterface $dest, array $options = array())
    {
        Util::pipe($this, $dest, $options);
        return $dest;
    }
    public function eof()
    {
        return !$this->isReadable();
    }
    public function __toString()
    {
        return '';
    }
    public function detach()
    {
        throw new \BadMethodCallException();
    }
    public function getSize()
    {
        return $this->size;
    }
    public function tell()
    {
        throw new \BadMethodCallException();
    }
    public function isSeekable()
    {
        return \false;
    }
    public function seek($offset, $whence = \SEEK_SET)
    {
        throw new \BadMethodCallException();
    }
    public function rewind()
    {
        throw new \BadMethodCallException();
    }
    public function isWritable()
    {
        return \false;
    }
    public function write($string)
    {
        throw new \BadMethodCallException();
    }
    public function read($length)
    {
        throw new \BadMethodCallException();
    }
    public function getContents()
    {
        throw new \BadMethodCallException();
    }
    public function getMetadata($key = null)
    {
        return $key === null ? array() : null;
    }
    /** @internal */
    public function handleEnd()
    {
        if ($this->position !== $this->size && $this->size !== null) {
            $this->emit('error', array(new \UnderflowException('Unexpected end of response body after ' . $this->position . '/' . $this->size . ' bytes')));
        } else {
            $this->emit('end');
        }
        $this->close();
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Io;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\ServerRequestInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Message\Response;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Message\ServerRequest;
use NightwatchAgent_kden27khxA4QoEfj\React\Socket\ConnectionInterface;
use Exception;
/**
 * [Internal] Parses an incoming request header from an input stream
 *
 * This is used internally to parse the request header from the connection and
 * then process the remaining connection as the request body.
 *
 * @event headers
 * @event error
 *
 * @internal
 */
class RequestHeaderParser extends EventEmitter
{
    private $maxSize = 8192;
    /** @var Clock */
    private $clock;
    /** @var array<string|int,array<string,string>> */
    private $connectionParams = array();
    public function __construct(Clock $clock)
    {
        $this->clock = $clock;
    }
    public function handle(ConnectionInterface $conn)
    {
        $buffer = '';
        $maxSize = $this->maxSize;
        $that = $this;
        $conn->on('data', $fn = function ($data) use (&$buffer, &$fn, $conn, $maxSize, $that) {
            // append chunk of data to buffer and look for end of request headers
            $buffer .= $data;
            $endOfHeader = \strpos($buffer, "\r\n\r\n");
            // reject request if buffer size is exceeded
            if ($endOfHeader > $maxSize || $endOfHeader === \false && isset($buffer[$maxSize])) {
                $conn->removeListener('data', $fn);
                $fn = null;
                $that->emit('error', array(new \OverflowException("Maximum header size of {$maxSize} exceeded.", Response::STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE), $conn));
                return;
            }
            // ignore incomplete requests
            if ($endOfHeader === \false) {
                return;
            }
            // request headers received => try to parse request
            $conn->removeListener('data', $fn);
            $fn = null;
            try {
                $request = $that->parseRequest((string) \substr($buffer, 0, $endOfHeader + 2), $conn);
            } catch (Exception $exception) {
                $buffer = '';
                $that->emit('error', array($exception, $conn));
                return;
            }
            $contentLength = 0;
            if ($request->hasHeader('Transfer-Encoding')) {
                $contentLength = null;
            } elseif ($request->hasHeader('Content-Length')) {
                $contentLength = (int) $request->getHeaderLine('Content-Length');
            }
            if ($contentLength === 0) {
                // happy path: request body is known to be empty
                $stream = new EmptyBodyStream();
                $request = $request->withBody($stream);
            } else {
                // otherwise body is present => delimit using Content-Length or ChunkedDecoder
                $stream = new CloseProtectionStream($conn);
                if ($contentLength !== null) {
                    $stream = new LengthLimitedStream($stream, $contentLength);
                } else {
                    $stream = new ChunkedDecoder($stream);
                }
                $request = $request->withBody(new HttpBodyStream($stream, $contentLength));
            }
            $bodyBuffer = isset($buffer[$endOfHeader + 4]) ? \substr($buffer, $endOfHeader + 4) : '';
            $buffer = '';
            $that->emit('headers', array($request, $conn));
            if ($bodyBuffer !== '') {
                $conn->emit('data', array($bodyBuffer));
            }
            // happy path: request body is known to be empty => immediately end stream
            if ($contentLength === 0) {
                $stream->emit('end');
                $stream->close();
            }
        });
    }
    /**
     * @param string $headers buffer string containing request headers only
     * @param ConnectionInterface $connection
     * @return ServerRequestInterface
     * @throws \InvalidArgumentException
     * @internal
     */
    public function parseRequest($headers, ConnectionInterface $connection)
    {
        // reuse same connection params for all server params for this connection
        $cid = \PHP_VERSION_ID < 70200 ? \spl_object_hash($connection) : \spl_object_id($connection);
        if (isset($this->connectionParams[$cid])) {
            $serverParams = $this->connectionParams[$cid];
        } else {
            // assign new server params for new connection
            $serverParams = array();
            // scheme is `http` unless TLS is used
            $localSocketUri = $connection->getLocalAddress();
            $localParts = $localSocketUri === null ? array() : \parse_url($localSocketUri);
            if (isset($localParts['scheme']) && $localParts['scheme'] === 'tls') {
                $serverParams['HTTPS'] = 'on';
            }
            // apply SERVER_ADDR and SERVER_PORT if server address is known
            // address should always be known, even for Unix domain sockets (UDS)
            // but skip UDS as it doesn't have a concept of host/port.
            if ($localSocketUri !== null && isset($localParts['host'], $localParts['port'])) {
                $serverParams['SERVER_ADDR'] = $localParts['host'];
                $serverParams['SERVER_PORT'] = $localParts['port'];
            }
            // apply REMOTE_ADDR and REMOTE_PORT if source address is known
            // address should always be known, unless this is over Unix domain sockets (UDS)
            $remoteSocketUri = $connection->getRemoteAddress();
            if ($remoteSocketUri !== null) {
                $remoteAddress = \parse_url($remoteSocketUri);
                $serverParams['REMOTE_ADDR'] = $remoteAddress['host'];
                $serverParams['REMOTE_PORT'] = $remoteAddress['port'];
            }
            // remember server params for all requests from this connection, reset on connection close
            $this->connectionParams[$cid] = $serverParams;
            $params =& $this->connectionParams;
            $connection->on('close', function () use (&$params, $cid) {
                assert(\is_array($params));
                unset($params[$cid]);
            });
        }
        // create new obj implementing ServerRequestInterface by preserving all
        // previous properties and restoring original request-target
        $serverParams['REQUEST_TIME'] = (int) $now = $this->clock->now();
        $serverParams['REQUEST_TIME_FLOAT'] = $now;
        return ServerRequest::parseMessage($headers, $serverParams);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Io;

use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\RequestInterface;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\ResponseInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Client\Client as HttpClient;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\PromiseInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\Deferred;
use NightwatchAgent_kden27khxA4QoEfj\React\Socket\ConnectorInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\ReadableStreamInterface;
/**
 * [Internal] Sends requests and receives responses
 *
 * The `Sender` is responsible for passing the [`RequestInterface`](#requestinterface) objects to
 * the underlying [`HttpClient`](https://github.com/reactphp/http-client) library
 * and keeps track of its transmission and converts its reponses back to [`ResponseInterface`](#responseinterface) objects.
 *
 * It also registers everything with the main [`EventLoop`](https://github.com/reactphp/event-loop#usage)
 * and the default [`Connector`](https://github.com/reactphp/socket-client) and [DNS `Resolver`](https://github.com/reactphp/dns).
 *
 * The `Sender` class mostly exists in order to abstract changes on the underlying
 * components away from this package in order to provide backwards and forwards
 * compatibility.
 *
 * @internal You SHOULD NOT rely on this API, it is subject to change without prior notice!
 * @see Browser
 */
class Sender
{
    /**
     * create a new default sender attached to the given event loop
     *
     * This method is used internally to create the "default sender".
     *
     * You may also use this method if you need custom DNS or connector
     * settings. You can use this method manually like this:
     *
     * ```php
     * $connector = new \React\Socket\Connector(array(), $loop);
     * $sender = \React\Http\Io\Sender::createFromLoop($loop, $connector);
     * ```
     *
     * @param LoopInterface $loop
     * @param ConnectorInterface|null $connector
     * @return self
     */
    public static function createFromLoop(LoopInterface $loop, ConnectorInterface $connector)
    {
        return new self(new HttpClient(new ClientConnectionManager($connector, $loop)));
    }
    private $http;
    /**
     * [internal] Instantiate Sender
     *
     * @param HttpClient $http
     * @internal
     */
    public function __construct(HttpClient $http)
    {
        $this->http = $http;
    }
    /**
     *
     * @internal
     * @param RequestInterface $request
     * @return PromiseInterface Promise<ResponseInterface, Exception>
     */
    public function send(RequestInterface $request)
    {
        // support HTTP/1.1 and HTTP/1.0 only, ensured by `Browser` already
        assert(\in_array($request->getProtocolVersion(), array('1.0', '1.1'), \true));
        $body = $request->getBody();
        $size = $body->getSize();
        if ($size !== null && $size !== 0) {
            // automatically assign a "Content-Length" request header if the body size is known and non-empty
            $request = $request->withHeader('Content-Length', (string) $size);
        } elseif ($size === 0 && \in_array($request->getMethod(), array('POST', 'PUT', 'PATCH'))) {
            // only assign a "Content-Length: 0" request header if the body is expected for certain methods
            $request = $request->withHeader('Content-Length', '0');
        } elseif ($body instanceof ReadableStreamInterface && $size !== 0 && $body->isReadable() && !$request->hasHeader('Content-Length')) {
            // use "Transfer-Encoding: chunked" when this is a streaming body and body size is unknown
            $request = $request->withHeader('Transfer-Encoding', 'chunked');
        } else {
            // do not use chunked encoding if size is known or if this is an empty request body
            $size = 0;
        }
        // automatically add `Authorization: Basic …` request header if URL includes `user:pass@host`
        if ($request->getUri()->getUserInfo() !== '' && !$request->hasHeader('Authorization')) {
            $request = $request->withHeader('Authorization', 'Basic ' . \base64_encode($request->getUri()->getUserInfo()));
        }
        $requestStream = $this->http->request($request);
        $deferred = new Deferred(function ($_, $reject) use ($requestStream) {
            // close request stream if request is cancelled
            $reject(new \RuntimeException('Request cancelled'));
            $requestStream->close();
        });
        $requestStream->on('error', function ($error) use ($deferred) {
            $deferred->reject($error);
        });
        $requestStream->on('response', function (ResponseInterface $response) use ($deferred, $request) {
            $deferred->resolve($response);
        });
        if ($body instanceof ReadableStreamInterface) {
            if ($body->isReadable()) {
                // length unknown => apply chunked transfer-encoding
                if ($size === null) {
                    $body = new ChunkedEncoder($body);
                }
                // pipe body into request stream
                // add dummy write to immediately start request even if body does not emit any data yet
                $body->pipe($requestStream);
                $requestStream->write('');
                $body->on('close', $close = function () use ($deferred, $requestStream) {
                    $deferred->reject(new \RuntimeException('Request failed because request body closed unexpectedly'));
                    $requestStream->close();
                });
                $body->on('error', function ($e) use ($deferred, $requestStream, $close, $body) {
                    $body->removeListener('close', $close);
                    $deferred->reject(new \RuntimeException('Request failed because request body reported an error', 0, $e));
                    $requestStream->close();
                });
                $body->on('end', function () use ($close, $body) {
                    $body->removeListener('close', $close);
                });
            } else {
                // stream is not readable => end request without body
                $requestStream->end();
            }
        } else {
            // body is fully buffered => write as one chunk
            $requestStream->end((string) $body);
        }
        return $deferred->promise();
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Io;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\ResponseInterface;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\ServerRequestInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Message\Response;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Message\ServerRequest;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\PromiseInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Socket\ConnectionInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Socket\ServerInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\ReadableStreamInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\WritableStreamInterface;
/**
 * The internal `StreamingServer` class is responsible for handling incoming connections and then
 * processing each incoming HTTP request.
 *
 * Unlike the [`HttpServer`](#httpserver) class, it does not buffer and parse the incoming
 * HTTP request body by default. This means that the request handler will be
 * invoked with a streaming request body. Once the request headers have been
 * received, it will invoke the request handler function. This request handler
 * function needs to be passed to the constructor and will be invoked with the
 * respective [request](#request) object and expects a [response](#response)
 * object in return:
 *
 * ```php
 * $server = new StreamingServer($loop, function (ServerRequestInterface $request) {
 *     return new Response(
 *         Response::STATUS_OK,
 *         array(
 *             'Content-Type' => 'text/plain'
 *         ),
 *         "Hello World!\n"
 *     );
 * });
 * ```
 *
 * Each incoming HTTP request message is always represented by the
 * [PSR-7 `ServerRequestInterface`](https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface),
 * see also following [request](#request) chapter for more details.
 * Each outgoing HTTP response message is always represented by the
 * [PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface),
 * see also following [response](#response) chapter for more details.
 *
 * In order to process any connections, the server needs to be attached to an
 * instance of `React\Socket\ServerInterface` through the [`listen()`](#listen) method
 * as described in the following chapter. In its most simple form, you can attach
 * this to a [`React\Socket\SocketServer`](https://github.com/reactphp/socket#socketserver)
 * in order to start a plaintext HTTP server like this:
 *
 * ```php
 * $server = new StreamingServer($loop, $handler);
 *
 * $socket = new React\Socket\SocketServer('0.0.0.0:8080', array(), $loop);
 * $server->listen($socket);
 * ```
 *
 * See also the [`listen()`](#listen) method and the [first example](examples) for more details.
 *
 * The `StreamingServer` class is considered advanced usage and unless you know
 * what you're doing, you're recommended to use the [`HttpServer`](#httpserver) class
 * instead. The `StreamingServer` class is specifically designed to help with
 * more advanced use cases where you want to have full control over consuming
 * the incoming HTTP request body and concurrency settings.
 *
 * In particular, this class does not buffer and parse the incoming HTTP request
 * in memory. It will invoke the request handler function once the HTTP request
 * headers have been received, i.e. before receiving the potentially much larger
 * HTTP request body. This means the [request](#request) passed to your request
 * handler function may not be fully compatible with PSR-7. See also
 * [streaming request](#streaming-request) below for more details.
 *
 * @see \React\Http\HttpServer
 * @see \React\Http\Message\Response
 * @see self::listen()
 * @internal
 */
final class StreamingServer extends EventEmitter
{
    private $callback;
    private $parser;
    /** @var Clock */
    private $clock;
    /**
     * Creates an HTTP server that invokes the given callback for each incoming HTTP request
     *
     * In order to process any connections, the server needs to be attached to an
     * instance of `React\Socket\ServerInterface` which emits underlying streaming
     * connections in order to then parse incoming data as HTTP.
     * See also [listen()](#listen) for more details.
     *
     * @param LoopInterface $loop
     * @param callable $requestHandler
     * @see self::listen()
     */
    public function __construct(LoopInterface $loop, $requestHandler)
    {
        if (!\is_callable($requestHandler)) {
            throw new \InvalidArgumentException('Invalid request handler given');
        }
        $this->callback = $requestHandler;
        $this->clock = new Clock($loop);
        $this->parser = new RequestHeaderParser($this->clock);
        $that = $this;
        $this->parser->on('headers', function (ServerRequestInterface $request, ConnectionInterface $conn) use ($that) {
            $that->handleRequest($conn, $request);
        });
        $this->parser->on('error', function (\Exception $e, ConnectionInterface $conn) use ($that) {
            $that->emit('error', array($e));
            // parsing failed => assume dummy request and send appropriate error
            $that->writeError($conn, $e->getCode() !== 0 ? $e->getCode() : Response::STATUS_BAD_REQUEST, new ServerRequest('GET', '/'));
        });
    }
    /**
     * Starts listening for HTTP requests on the given socket server instance
     *
     * @param ServerInterface $socket
     * @see \React\Http\HttpServer::listen()
     */
    public function listen(ServerInterface $socket)
    {
        $socket->on('connection', array($this->parser, 'handle'));
    }
    /** @internal */
    public function handleRequest(ConnectionInterface $conn, ServerRequestInterface $request)
    {
        if ($request->getProtocolVersion() !== '1.0' && '100-continue' === \strtolower($request->getHeaderLine('Expect'))) {
            $conn->write("HTTP/1.1 100 Continue\r\n\r\n");
        }
        // execute request handler callback
        $callback = $this->callback;
        try {
            $response = $callback($request);
        } catch (\Exception $error) {
            // request handler callback throws an Exception
            $response = Promise\reject($error);
        } catch (\Throwable $error) {
            // @codeCoverageIgnoreStart
            // request handler callback throws a PHP7+ Error
            $response = Promise\reject($error);
            // @codeCoverageIgnoreEnd
        }
        // cancel pending promise once connection closes
        $connectionOnCloseResponseCancelerHandler = function () {
        };
        if ($response instanceof PromiseInterface && \method_exists($response, 'cancel')) {
            $connectionOnCloseResponseCanceler = function () use ($response) {
                $response->cancel();
            };
            $connectionOnCloseResponseCancelerHandler = function () use ($connectionOnCloseResponseCanceler, $conn) {
                if ($connectionOnCloseResponseCanceler !== null) {
                    $conn->removeListener('close', $connectionOnCloseResponseCanceler);
                }
            };
            $conn->on('close', $connectionOnCloseResponseCanceler);
        }
        // happy path: response returned, handle and return immediately
        if ($response instanceof ResponseInterface) {
            return $this->handleResponse($conn, $request, $response);
        }
        // did not return a promise? this is an error, convert into one for rejection below.
        if (!$response instanceof PromiseInterface) {
            $response = Promise\resolve($response);
        }
        $that = $this;
        $response->then(function ($response) use ($that, $conn, $request) {
            if (!$response instanceof ResponseInterface) {
                $message = 'The response callback is expected to resolve with an object implementing Psr\Http\Message\ResponseInterface, but resolved with "%s" instead.';
                $message = \sprintf($message, \is_object($response) ? \get_class($response) : \gettype($response));
                $exception = new \RuntimeException($message);
                $that->emit('error', array($exception));
                return $that->writeError($conn, Response::STATUS_INTERNAL_SERVER_ERROR, $request);
            }
            $that->handleResponse($conn, $request, $response);
        }, function ($error) use ($that, $conn, $request) {
            $message = 'The response callback is expected to resolve with an object implementing Psr\Http\Message\ResponseInterface, but rejected with "%s" instead.';
            $message = \sprintf($message, \is_object($error) ? \get_class($error) : \gettype($error));
            $previous = null;
            if ($error instanceof \Throwable || $error instanceof \Exception) {
                $previous = $error;
            }
            $exception = new \RuntimeException($message, 0, $previous);
            $that->emit('error', array($exception));
            return $that->writeError($conn, Response::STATUS_INTERNAL_SERVER_ERROR, $request);
        })->then($connectionOnCloseResponseCancelerHandler, $connectionOnCloseResponseCancelerHandler);
    }
    /** @internal */
    public function writeError(ConnectionInterface $conn, $code, ServerRequestInterface $request)
    {
        $response = new Response($code, array('Content-Type' => 'text/plain', 'Connection' => 'close'), 'Error ' . $code);
        // append reason phrase to response body if known
        $reason = $response->getReasonPhrase();
        if ($reason !== '') {
            $body = $response->getBody();
            $body->seek(0, \SEEK_END);
            $body->write(': ' . $reason);
        }
        $this->handleResponse($conn, $request, $response);
    }
    /** @internal */
    public function handleResponse(ConnectionInterface $connection, ServerRequestInterface $request, ResponseInterface $response)
    {
        // return early and close response body if connection is already closed
        $body = $response->getBody();
        if (!$connection->isWritable()) {
            $body->close();
            return;
        }
        $code = $response->getStatusCode();
        $method = $request->getMethod();
        // assign HTTP protocol version from request automatically
        $version = $request->getProtocolVersion();
        $response = $response->withProtocolVersion($version);
        // assign default "Server" header automatically
        if (!$response->hasHeader('Server')) {
            $response = $response->withHeader('Server', 'ReactPHP/1');
        } elseif ($response->getHeaderLine('Server') === '') {
            $response = $response->withoutHeader('Server');
        }
        // assign default "Date" header from current time automatically
        if (!$response->hasHeader('Date')) {
            // IMF-fixdate  = day-name "," SP date1 SP time-of-day SP GMT
            $response = $response->withHeader('Date', gmdate('D, d M Y H:i:s', (int) $this->clock->now()) . ' GMT');
        } elseif ($response->getHeaderLine('Date') === '') {
            $response = $response->withoutHeader('Date');
        }
        // assign "Content-Length" header automatically
        $chunked = \false;
        if ($method === 'CONNECT' && $code >= 200 && $code < 300 || $code >= 100 && $code < 200 || $code === Response::STATUS_NO_CONTENT) {
            // 2xx response to CONNECT and 1xx and 204 MUST NOT include Content-Length or Transfer-Encoding header
            $response = $response->withoutHeader('Content-Length');
        } elseif ($method === 'HEAD' && $response->hasHeader('Content-Length')) {
            // HEAD Request: preserve explicit Content-Length
        } elseif ($code === Response::STATUS_NOT_MODIFIED && ($response->hasHeader('Content-Length') || $body->getSize() === 0)) {
            // 304 Not Modified: preserve explicit Content-Length and preserve missing header if body is empty
        } elseif ($body->getSize() !== null) {
            // assign Content-Length header when using a "normal" buffered body string
            $response = $response->withHeader('Content-Length', (string) $body->getSize());
        } elseif (!$response->hasHeader('Content-Length') && $version === '1.1') {
            // assign chunked transfer-encoding if no 'content-length' is given for HTTP/1.1 responses
            $chunked = \true;
        }
        // assign "Transfer-Encoding" header automatically
        if ($chunked) {
            $response = $response->withHeader('Transfer-Encoding', 'chunked');
        } else {
            // remove any Transfer-Encoding headers unless automatically enabled above
            $response = $response->withoutHeader('Transfer-Encoding');
        }
        // assign "Connection" header automatically
        $persist = \false;
        if ($code === Response::STATUS_SWITCHING_PROTOCOLS) {
            // 101 (Switching Protocols) response uses Connection: upgrade header
            // This implies that this stream now uses another protocol and we
            // may not persist this connection for additional requests.
            $response = $response->withHeader('Connection', 'upgrade');
        } elseif (\strtolower($request->getHeaderLine('Connection')) === 'close' || \strtolower($response->getHeaderLine('Connection')) === 'close') {
            // obey explicit "Connection: close" request header or response header if present
            $response = $response->withHeader('Connection', 'close');
        } elseif ($version === '1.1') {
            // HTTP/1.1 assumes persistent connection support by default, so we don't need to inform client
            $persist = \true;
        } elseif (strtolower($request->getHeaderLine('Connection')) === 'keep-alive') {
            // obey explicit "Connection: keep-alive" request header and inform client
            $persist = \true;
            $response = $response->withHeader('Connection', 'keep-alive');
        } else {
            // remove any Connection headers unless automatically enabled above
            $response = $response->withoutHeader('Connection');
        }
        // 101 (Switching Protocols) response (for Upgrade request) forwards upgraded data through duplex stream
        // 2xx (Successful) response to CONNECT forwards tunneled application data through duplex stream
        if (($code === Response::STATUS_SWITCHING_PROTOCOLS || $method === 'CONNECT' && $code >= 200 && $code < 300) && $body instanceof HttpBodyStream && $body->input instanceof WritableStreamInterface) {
            if ($request->getBody()->isReadable()) {
                // request is still streaming => wait for request close before forwarding following data from connection
                $request->getBody()->on('close', function () use ($connection, $body) {
                    if ($body->input->isWritable()) {
                        $connection->pipe($body->input);
                        $connection->resume();
                    }
                });
            } elseif ($body->input->isWritable()) {
                // request already closed => forward following data from connection
                $connection->pipe($body->input);
                $connection->resume();
            }
        }
        // build HTTP response header by appending status line and header fields
        $expected = 0;
        $headers = "HTTP/" . $version . " " . $code . " " . $response->getReasonPhrase() . "\r\n";
        foreach ($response->getHeaders() as $name => $values) {
            if (\strpos($name, ':') !== \false) {
                $expected = -1;
                break;
            }
            foreach ($values as $value) {
                $headers .= $name . ": " . $value . "\r\n";
                ++$expected;
            }
        }
        /** @var array $m legacy PHP 5.3 only */
        if ($code < 100 || $code > 999 || \substr_count($headers, "\n") !== $expected + 1 || (\PHP_VERSION_ID >= 50400 ? \preg_match_all(AbstractMessage::REGEX_HEADERS, $headers) : \preg_match_all(AbstractMessage::REGEX_HEADERS, $headers, $m)) !== $expected) {
            $this->emit('error', array(new \InvalidArgumentException('Unable to send response with invalid response headers')));
            $this->writeError($connection, Response::STATUS_INTERNAL_SERVER_ERROR, $request);
            return;
        }
        // response to HEAD and 1xx, 204 and 304 responses MUST NOT include a body
        // exclude status 101 (Switching Protocols) here for Upgrade request handling above
        if ($method === 'HEAD' || $code >= 100 && $code < 200 && $code !== Response::STATUS_SWITCHING_PROTOCOLS || $code === Response::STATUS_NO_CONTENT || $code === Response::STATUS_NOT_MODIFIED) {
            $body->close();
            $body = '';
        }
        // this is a non-streaming response body or the body stream already closed?
        if (!$body instanceof ReadableStreamInterface || !$body->isReadable()) {
            // add final chunk if a streaming body is already closed and uses `Transfer-Encoding: chunked`
            if ($body instanceof ReadableStreamInterface && $chunked) {
                $body = "0\r\n\r\n";
            }
            // write response headers and body
            $connection->write($headers . "\r\n" . $body);
            // either wait for next request over persistent connection or end connection
            if ($persist) {
                $this->parser->handle($connection);
            } else {
                $connection->end();
            }
            return;
        }
        $connection->write($headers . "\r\n");
        if ($chunked) {
            $body = new ChunkedEncoder($body);
        }
        // Close response stream once connection closes.
        // Note that this TCP/IP close detection may take some time,
        // in particular this may only fire on a later read/write attempt.
        $connection->on('close', array($body, 'close'));
        // write streaming body and then wait for next request over persistent connection
        if ($persist) {
            $body->pipe($connection, array('end' => \false));
            $parser = $this->parser;
            $body->on('end', function () use ($connection, $parser, $body) {
                $connection->removeListener('close', array($body, 'close'));
                $parser->handle($connection);
            });
        } else {
            $body->pipe($connection);
        }
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Io;

use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\RequestInterface;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\ResponseInterface;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\UriInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Message\Response;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Message\ResponseException;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Message\Uri;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\Deferred;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\Promise;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\PromiseInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\ReadableStreamInterface;
/**
 * @internal
 */
class Transaction
{
    private $sender;
    private $loop;
    // context: http.timeout (ini_get('default_socket_timeout'): 60)
    private $timeout;
    // context: http.follow_location (true)
    private $followRedirects = \true;
    // context: http.max_redirects (10)
    private $maxRedirects = 10;
    // context: http.ignore_errors (false)
    private $obeySuccessCode = \true;
    private $streaming = \false;
    private $maximumSize = 16777216;
    // 16 MiB = 2^24 bytes
    public function __construct(Sender $sender, LoopInterface $loop)
    {
        $this->sender = $sender;
        $this->loop = $loop;
    }
    /**
     * @param array $options
     * @return self returns new instance, without modifying existing instance
     */
    public function withOptions(array $options)
    {
        $transaction = clone $this;
        foreach ($options as $name => $value) {
            if (property_exists($transaction, $name)) {
                // restore default value if null is given
                if ($value === null) {
                    $default = new self($this->sender, $this->loop);
                    $value = $default->{$name};
                }
                $transaction->{$name} = $value;
            }
        }
        return $transaction;
    }
    public function send(RequestInterface $request)
    {
        $state = new ClientRequestState();
        $deferred = new Deferred(function () use ($state) {
            if ($state->pending !== null) {
                $state->pending->cancel();
                $state->pending = null;
            }
        });
        // use timeout from options or default to PHP's default_socket_timeout (60)
        $timeout = (float) ($this->timeout !== null ? $this->timeout : ini_get("default_socket_timeout"));
        $loop = $this->loop;
        $this->next($request, $deferred, $state)->then(function (ResponseInterface $response) use ($state, $deferred, $loop, &$timeout) {
            if ($state->timeout !== null) {
                $loop->cancelTimer($state->timeout);
                $state->timeout = null;
            }
            $timeout = -1;
            $deferred->resolve($response);
        }, function ($e) use ($state, $deferred, $loop, &$timeout) {
            if ($state->timeout !== null) {
                $loop->cancelTimer($state->timeout);
                $state->timeout = null;
            }
            $timeout = -1;
            $deferred->reject($e);
        });
        if ($timeout < 0) {
            return $deferred->promise();
        }
        $body = $request->getBody();
        if ($body instanceof ReadableStreamInterface && $body->isReadable()) {
            $that = $this;
            $body->on('close', function () use ($that, $deferred, $state, &$timeout) {
                if ($timeout >= 0) {
                    $that->applyTimeout($deferred, $state, $timeout);
                }
            });
        } else {
            $this->applyTimeout($deferred, $state, $timeout);
        }
        return $deferred->promise();
    }
    /**
     * @internal
     * @param number $timeout
     * @return void
     */
    public function applyTimeout(Deferred $deferred, ClientRequestState $state, $timeout)
    {
        $state->timeout = $this->loop->addTimer($timeout, function () use ($timeout, $deferred, $state) {
            $deferred->reject(new \RuntimeException('Request timed out after ' . $timeout . ' seconds'));
            if ($state->pending !== null) {
                $state->pending->cancel();
                $state->pending = null;
            }
        });
    }
    private function next(RequestInterface $request, Deferred $deferred, ClientRequestState $state)
    {
        $this->progress('request', array($request));
        $that = $this;
        ++$state->numRequests;
        $promise = $this->sender->send($request);
        if (!$this->streaming) {
            $promise = $promise->then(function ($response) use ($deferred, $state, $that) {
                return $that->bufferResponse($response, $deferred, $state);
            });
        }
        $state->pending = $promise;
        return $promise->then(function (ResponseInterface $response) use ($request, $that, $deferred, $state) {
            return $that->onResponse($response, $request, $deferred, $state);
        });
    }
    /**
     * @internal
     * @return PromiseInterface Promise<ResponseInterface, Exception>
     */
    public function bufferResponse(ResponseInterface $response, Deferred $deferred, ClientRequestState $state)
    {
        $body = $response->getBody();
        $size = $body->getSize();
        if ($size !== null && $size > $this->maximumSize) {
            $body->close();
            return \NightwatchAgent_kden27khxA4QoEfj\React\Promise\reject(new \OverflowException('Response body size of ' . $size . ' bytes exceeds maximum of ' . $this->maximumSize . ' bytes', \defined('SOCKET_EMSGSIZE') ? \SOCKET_EMSGSIZE : 90));
        }
        // body is not streaming => already buffered
        if (!$body instanceof ReadableStreamInterface) {
            return \NightwatchAgent_kden27khxA4QoEfj\React\Promise\resolve($response);
        }
        /** @var ?\Closure $closer */
        $closer = null;
        $maximumSize = $this->maximumSize;
        return $state->pending = new Promise(function ($resolve, $reject) use ($body, $maximumSize, $response, &$closer) {
            // resolve with current buffer when stream closes successfully
            $buffer = '';
            $body->on('close', $closer = function () use (&$buffer, $response, $maximumSize, $resolve, $reject) {
                $resolve($response->withBody(new BufferedBody($buffer)));
            });
            // buffer response body data in memory
            $body->on('data', function ($data) use (&$buffer, $maximumSize, $body, $closer, $reject) {
                $buffer .= $data;
                // close stream and reject promise if limit is exceeded
                if (isset($buffer[$maximumSize])) {
                    $buffer = '';
                    assert($closer instanceof \Closure);
                    $body->removeListener('close', $closer);
                    $body->close();
                    $reject(new \OverflowException('Response body size exceeds maximum of ' . $maximumSize . ' bytes', \defined('SOCKET_EMSGSIZE') ? \SOCKET_EMSGSIZE : 90));
                }
            });
            // reject buffering if body emits error
            $body->on('error', function (\Exception $e) use ($reject) {
                $reject(new \RuntimeException('Error while buffering response body: ' . $e->getMessage(), $e->getCode(), $e));
            });
        }, function () use ($body, &$closer) {
            // cancelled buffering: remove close handler to avoid resolving, then close and reject
            assert($closer instanceof \Closure);
            $body->removeListener('close', $closer);
            $body->close();
            throw new \RuntimeException('Cancelled buffering response body');
        });
    }
    /**
     * @internal
     * @throws ResponseException
     * @return ResponseInterface|PromiseInterface
     */
    public function onResponse(ResponseInterface $response, RequestInterface $request, Deferred $deferred, ClientRequestState $state)
    {
        $this->progress('response', array($response, $request));
        // follow 3xx (Redirection) response status codes if Location header is present and not explicitly disabled
        // @link https://tools.ietf.org/html/rfc7231#section-6.4
        if ($this->followRedirects && ($response->getStatusCode() >= 300 && $response->getStatusCode() < 400) && $response->hasHeader('Location')) {
            return $this->onResponseRedirect($response, $request, $deferred, $state);
        }
        // only status codes 200-399 are considered to be valid, reject otherwise
        if ($this->obeySuccessCode && ($response->getStatusCode() < 200 || $response->getStatusCode() >= 400)) {
            throw new ResponseException($response);
        }
        // resolve our initial promise
        return $response;
    }
    /**
     * @param ResponseInterface $response
     * @param RequestInterface $request
     * @param Deferred $deferred
     * @param ClientRequestState $state
     * @return PromiseInterface
     * @throws \RuntimeException
     */
    private function onResponseRedirect(ResponseInterface $response, RequestInterface $request, Deferred $deferred, ClientRequestState $state)
    {
        // resolve location relative to last request URI
        $location = Uri::resolve($request->getUri(), new Uri($response->getHeaderLine('Location')));
        $request = $this->makeRedirectRequest($request, $location, $response->getStatusCode());
        $this->progress('redirect', array($request));
        if ($state->numRequests >= $this->maxRedirects) {
            throw new \RuntimeException('Maximum number of redirects (' . $this->maxRedirects . ') exceeded');
        }
        return $this->next($request, $deferred, $state);
    }
    /**
     * @param RequestInterface $request
     * @param UriInterface $location
     * @param int $statusCode
     * @return RequestInterface
     * @throws \RuntimeException
     */
    private function makeRedirectRequest(RequestInterface $request, UriInterface $location, $statusCode)
    {
        // Remove authorization if changing hostnames (but not if just changing ports or protocols).
        $originalHost = $request->getUri()->getHost();
        if ($location->getHost() !== $originalHost) {
            $request = $request->withoutHeader('Authorization');
        }
        $request = $request->withoutHeader('Host')->withUri($location);
        if ($statusCode === Response::STATUS_TEMPORARY_REDIRECT || $statusCode === Response::STATUS_PERMANENT_REDIRECT) {
            if ($request->getBody() instanceof ReadableStreamInterface) {
                throw new \RuntimeException('Unable to redirect request with streaming body');
            }
        } else {
            $request = $request->withMethod($request->getMethod() === 'HEAD' ? 'HEAD' : 'GET')->withoutHeader('Content-Type')->withoutHeader('Content-Length')->withBody(new BufferedBody(''));
        }
        return $request;
    }
    private function progress($name, array $args = array())
    {
        return;
        echo $name;
        foreach ($args as $arg) {
            echo ' ';
            if ($arg instanceof ResponseInterface) {
                echo 'HTTP/' . $arg->getProtocolVersion() . ' ' . $arg->getStatusCode() . ' ' . $arg->getReasonPhrase();
            } elseif ($arg instanceof RequestInterface) {
                echo $arg->getMethod() . ' ' . $arg->getRequestTarget() . ' HTTP/' . $arg->getProtocolVersion();
            } else {
                echo $arg;
            }
        }
        echo \PHP_EOL;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Io;

use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\StreamInterface;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\UploadedFileInterface;
use InvalidArgumentException;
use RuntimeException;
/**
 * [Internal] Implementation of the PSR-7 `UploadedFileInterface`
 *
 * This is used internally to represent each incoming file upload.
 *
 * Note that this is an internal class only and nothing you should usually care
 * about. See the `UploadedFileInterface` for more details.
 *
 * @see UploadedFileInterface
 * @internal
 */
final class UploadedFile implements UploadedFileInterface
{
    /**
     * @var StreamInterface
     */
    private $stream;
    /**
     * @var int
     */
    private $size;
    /**
     * @var int
     */
    private $error;
    /**
     * @var string
     */
    private $filename;
    /**
     * @var string
     */
    private $mediaType;
    /**
     * @param StreamInterface $stream
     * @param int $size
     * @param int $error
     * @param string $filename
     * @param string $mediaType
     */
    public function __construct(StreamInterface $stream, $size, $error, $filename, $mediaType)
    {
        $this->stream = $stream;
        $this->size = $size;
        if (!\is_int($error) || !\in_array($error, array(\UPLOAD_ERR_OK, \UPLOAD_ERR_INI_SIZE, \UPLOAD_ERR_FORM_SIZE, \UPLOAD_ERR_PARTIAL, \UPLOAD_ERR_NO_FILE, \UPLOAD_ERR_NO_TMP_DIR, \UPLOAD_ERR_CANT_WRITE, \UPLOAD_ERR_EXTENSION))) {
            throw new InvalidArgumentException('Invalid error code, must be an UPLOAD_ERR_* constant');
        }
        $this->error = $error;
        $this->filename = $filename;
        $this->mediaType = $mediaType;
    }
    /**
     * {@inheritdoc}
     */
    public function getStream()
    {
        if ($this->error !== \UPLOAD_ERR_OK) {
            throw new RuntimeException('Cannot retrieve stream due to upload error');
        }
        return $this->stream;
    }
    /**
     * {@inheritdoc}
     */
    public function moveTo($targetPath)
    {
        throw new RuntimeException('Not implemented');
    }
    /**
     * {@inheritdoc}
     */
    public function getSize()
    {
        return $this->size;
    }
    /**
     * {@inheritdoc}
     */
    public function getError()
    {
        return $this->error;
    }
    /**
     * {@inheritdoc}
     */
    public function getClientFilename()
    {
        return $this->filename;
    }
    /**
     * {@inheritdoc}
     */
    public function getClientMediaType()
    {
        return $this->mediaType;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Message;

use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\RequestInterface;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\StreamInterface;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\UriInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Io\AbstractRequest;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Io\BufferedBody;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Io\ReadableBodyStream;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\ReadableStreamInterface;
/**
 * Respresents an outgoing HTTP request message.
 *
 * This class implements the
 * [PSR-7 `RequestInterface`](https://www.php-fig.org/psr/psr-7/#32-psrhttpmessagerequestinterface)
 * which extends the
 * [PSR-7 `MessageInterface`](https://www.php-fig.org/psr/psr-7/#31-psrhttpmessagemessageinterface).
 *
 * This is mostly used internally to represent each outgoing HTTP request
 * message for the HTTP client implementation. Likewise, you can also use this
 * class with other HTTP client implementations and for tests.
 *
 * > Internally, this implementation builds on top of a base class which is
 *   considered an implementation detail that may change in the future.
 *
 * @see RequestInterface
 */
final class Request extends AbstractRequest implements RequestInterface
{
    /**
     * @param string                                         $method  HTTP method for the request.
     * @param string|UriInterface                            $url     URL for the request.
     * @param array<string,string|string[]>                  $headers Headers for the message.
     * @param string|ReadableStreamInterface|StreamInterface $body    Message body.
     * @param string                                         $version HTTP protocol version.
     * @throws \InvalidArgumentException for an invalid URL or body
     */
    public function __construct($method, $url, array $headers = array(), $body = '', $version = '1.1')
    {
        if (\is_string($body)) {
            $body = new BufferedBody($body);
        } elseif ($body instanceof ReadableStreamInterface && !$body instanceof StreamInterface) {
            $body = new ReadableBodyStream($body);
        } elseif (!$body instanceof StreamInterface) {
            throw new \InvalidArgumentException('Invalid request body given');
        }
        parent::__construct($method, $url, $headers, $body, $version);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Message;

use NightwatchAgent_kden27khxA4QoEfj\Fig\Http\Message\StatusCodeInterface;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\ResponseInterface;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\StreamInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Io\AbstractMessage;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Io\BufferedBody;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Io\HttpBodyStream;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\ReadableStreamInterface;
/**
 * Represents an outgoing server response message.
 *
 * ```php
 * $response = new React\Http\Message\Response(
 *     React\Http\Message\Response::STATUS_OK,
 *     array(
 *         'Content-Type' => 'text/html'
 *     ),
 *     "<html>Hello world!</html>\n"
 * );
 * ```
 *
 * This class implements the
 * [PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface)
 * which in turn extends the
 * [PSR-7 `MessageInterface`](https://www.php-fig.org/psr/psr-7/#31-psrhttpmessagemessageinterface).
 *
 * On top of this, this class implements the
 * [PSR-7 Message Util `StatusCodeInterface`](https://github.com/php-fig/http-message-util/blob/master/src/StatusCodeInterface.php)
 * which means that most common HTTP status codes are available as class
 * constants with the `STATUS_*` prefix. For instance, the `200 OK` and
 * `404 Not Found` status codes can used as `Response::STATUS_OK` and
 * `Response::STATUS_NOT_FOUND` respectively.
 *
 * > Internally, this implementation builds on top a base class which is
 *   considered an implementation detail that may change in the future.
 *
 * @see \Psr\Http\Message\ResponseInterface
 */
final class Response extends AbstractMessage implements ResponseInterface, StatusCodeInterface
{
    /**
     * Create an HTML response
     *
     * ```php
     * $html = <<<HTML
     * <!doctype html>
     * <html>
     * <body>Hello wörld!</body>
     * </html>
     *
     * HTML;
     *
     * $response = React\Http\Message\Response::html($html);
     * ```
     *
     * This is a convenient shortcut method that returns the equivalent of this:
     *
     * ```
     * $response = new React\Http\Message\Response(
     *     React\Http\Message\Response::STATUS_OK,
     *     [
     *         'Content-Type' => 'text/html; charset=utf-8'
     *     ],
     *     $html
     * );
     * ```
     *
     * This method always returns a response with a `200 OK` status code and
     * the appropriate `Content-Type` response header for the given HTTP source
     * string encoded in UTF-8 (Unicode). It's generally recommended to end the
     * given plaintext string with a trailing newline.
     *
     * If you want to use a different status code or custom HTTP response
     * headers, you can manipulate the returned response object using the
     * provided PSR-7 methods or directly instantiate a custom HTTP response
     * object using the `Response` constructor:
     *
     * ```php
     * $response = React\Http\Message\Response::html(
     *     "<h1>Error</h1>\n<p>Invalid user name given.</p>\n"
     * )->withStatus(React\Http\Message\Response::STATUS_BAD_REQUEST);
     * ```
     *
     * @param string $html
     * @return self
     */
    public static function html($html)
    {
        return new self(self::STATUS_OK, array('Content-Type' => 'text/html; charset=utf-8'), $html);
    }
    /**
     * Create a JSON response
     *
     * ```php
     * $response = React\Http\Message\Response::json(['name' => 'Alice']);
     * ```
     *
     * This is a convenient shortcut method that returns the equivalent of this:
     *
     * ```
     * $response = new React\Http\Message\Response(
     *     React\Http\Message\Response::STATUS_OK,
     *     [
     *         'Content-Type' => 'application/json'
     *     ],
     *     json_encode(
     *         ['name' => 'Alice'],
     *         JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRESERVE_ZERO_FRACTION
     *     ) . "\n"
     * );
     * ```
     *
     * This method always returns a response with a `200 OK` status code and
     * the appropriate `Content-Type` response header for the given structured
     * data encoded as a JSON text.
     *
     * The given structured data will be encoded as a JSON text. Any `string`
     * values in the data must be encoded in UTF-8 (Unicode). If the encoding
     * fails, this method will throw an `InvalidArgumentException`.
     *
     * By default, the given structured data will be encoded with the flags as
     * shown above. This includes pretty printing (PHP 5.4+) and preserving
     * zero fractions for `float` values (PHP 5.6.6+) to ease debugging. It is
     * assumed any additional data overhead is usually compensated by using HTTP
     * response compression.
     *
     * If you want to use a different status code or custom HTTP response
     * headers, you can manipulate the returned response object using the
     * provided PSR-7 methods or directly instantiate a custom HTTP response
     * object using the `Response` constructor:
     *
     * ```php
     * $response = React\Http\Message\Response::json(
     *     ['error' => 'Invalid user name given']
     * )->withStatus(React\Http\Message\Response::STATUS_BAD_REQUEST);
     * ```
     *
     * @param mixed $data
     * @return self
     * @throws \InvalidArgumentException when encoding fails
     */
    public static function json($data)
    {
        $json = @\json_encode($data, (\defined('JSON_PRETTY_PRINT') ? \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE : 0) | (\defined('JSON_PRESERVE_ZERO_FRACTION') ? \JSON_PRESERVE_ZERO_FRACTION : 0));
        // throw on error, now `false` but used to be `(string) "null"` before PHP 5.5
        if ($json === \false || \PHP_VERSION_ID < 50500 && \json_last_error() !== \JSON_ERROR_NONE) {
            throw new \InvalidArgumentException('Unable to encode given data as JSON' . (\function_exists('json_last_error_msg') ? ': ' . \json_last_error_msg() : ''), \json_last_error());
        }
        return new self(self::STATUS_OK, array('Content-Type' => 'application/json'), $json . "\n");
    }
    /**
     * Create a plaintext response
     *
     * ```php
     * $response = React\Http\Message\Response::plaintext("Hello wörld!\n");
     * ```
     *
     * This is a convenient shortcut method that returns the equivalent of this:
     *
     * ```
     * $response = new React\Http\Message\Response(
     *     React\Http\Message\Response::STATUS_OK,
     *     [
     *         'Content-Type' => 'text/plain; charset=utf-8'
     *     ],
     *     "Hello wörld!\n"
     * );
     * ```
     *
     * This method always returns a response with a `200 OK` status code and
     * the appropriate `Content-Type` response header for the given plaintext
     * string encoded in UTF-8 (Unicode). It's generally recommended to end the
     * given plaintext string with a trailing newline.
     *
     * If you want to use a different status code or custom HTTP response
     * headers, you can manipulate the returned response object using the
     * provided PSR-7 methods or directly instantiate a custom HTTP response
     * object using the `Response` constructor:
     *
     * ```php
     * $response = React\Http\Message\Response::plaintext(
     *     "Error: Invalid user name given.\n"
     * )->withStatus(React\Http\Message\Response::STATUS_BAD_REQUEST);
     * ```
     *
     * @param string $text
     * @return self
     */
    public static function plaintext($text)
    {
        return new self(self::STATUS_OK, array('Content-Type' => 'text/plain; charset=utf-8'), $text);
    }
    /**
     * Create an XML response
     *
     * ```php
     * $xml = <<<XML
     * <?xml version="1.0" encoding="utf-8"?>
     * <body>
     *     <greeting>Hello wörld!</greeting>
     * </body>
     *
     * XML;
     *
     * $response = React\Http\Message\Response::xml($xml);
     * ```
     *
     * This is a convenient shortcut method that returns the equivalent of this:
     *
     * ```
     * $response = new React\Http\Message\Response(
     *     React\Http\Message\Response::STATUS_OK,
     *     [
     *         'Content-Type' => 'application/xml'
     *     ],
     *     $xml
     * );
     * ```
     *
     * This method always returns a response with a `200 OK` status code and
     * the appropriate `Content-Type` response header for the given XML source
     * string. It's generally recommended to use UTF-8 (Unicode) and specify
     * this as part of the leading XML declaration and to end the given XML
     * source string with a trailing newline.
     *
     * If you want to use a different status code or custom HTTP response
     * headers, you can manipulate the returned response object using the
     * provided PSR-7 methods or directly instantiate a custom HTTP response
     * object using the `Response` constructor:
     *
     * ```php
     * $response = React\Http\Message\Response::xml(
     *     "<error><message>Invalid user name given.</message></error>\n"
     * )->withStatus(React\Http\Message\Response::STATUS_BAD_REQUEST);
     * ```
     *
     * @param string $xml
     * @return self
     */
    public static function xml($xml)
    {
        return new self(self::STATUS_OK, array('Content-Type' => 'application/xml'), $xml);
    }
    /**
     * @var bool
     * @see self::$phrasesMap
     */
    private static $phrasesInitialized = \false;
    /**
     * Map of standard HTTP status codes to standard reason phrases.
     *
     * This map will be fully populated with all standard reason phrases on
     * first access. By default, it only contains a subset of HTTP status codes
     * that have a custom mapping to reason phrases (such as those with dashes
     * and all caps words). See `self::STATUS_*` for all possible status code
     * constants.
     *
     * @var array<int,string>
     * @see self::STATUS_*
     * @see self::getReasonPhraseForStatusCode()
     */
    private static $phrasesMap = array(200 => 'OK', 203 => 'Non-Authoritative Information', 207 => 'Multi-Status', 226 => 'IM Used', 414 => 'URI Too Large', 418 => 'I\'m a teapot', 505 => 'HTTP Version Not Supported');
    /** @var int */
    private $statusCode;
    /** @var string */
    private $reasonPhrase;
    /**
     * @param int                                            $status  HTTP status code (e.g. 200/404), see `self::STATUS_*` constants
     * @param array<string,string|string[]>                  $headers additional response headers
     * @param string|ReadableStreamInterface|StreamInterface $body    response body
     * @param string                                         $version HTTP protocol version (e.g. 1.1/1.0)
     * @param ?string                                        $reason  custom HTTP response phrase
     * @throws \InvalidArgumentException for an invalid body
     */
    public function __construct($status = self::STATUS_OK, array $headers = array(), $body = '', $version = '1.1', $reason = null)
    {
        if (\is_string($body)) {
            $body = new BufferedBody($body);
        } elseif ($body instanceof ReadableStreamInterface && !$body instanceof StreamInterface) {
            $body = new HttpBodyStream($body, null);
        } elseif (!$body instanceof StreamInterface) {
            throw new \InvalidArgumentException('Invalid response body given');
        }
        parent::__construct($version, $headers, $body);
        $this->statusCode = (int) $status;
        $this->reasonPhrase = $reason !== '' && $reason !== null ? (string) $reason : self::getReasonPhraseForStatusCode($status);
    }
    public function getStatusCode()
    {
        return $this->statusCode;
    }
    public function withStatus($code, $reasonPhrase = '')
    {
        if ((string) $reasonPhrase === '') {
            $reasonPhrase = self::getReasonPhraseForStatusCode($code);
        }
        if ($this->statusCode === (int) $code && $this->reasonPhrase === (string) $reasonPhrase) {
            return $this;
        }
        $response = clone $this;
        $response->statusCode = (int) $code;
        $response->reasonPhrase = (string) $reasonPhrase;
        return $response;
    }
    public function getReasonPhrase()
    {
        return $this->reasonPhrase;
    }
    /**
     * @param int $code
     * @return string default reason phrase for given status code or empty string if unknown
     */
    private static function getReasonPhraseForStatusCode($code)
    {
        if (!self::$phrasesInitialized) {
            self::$phrasesInitialized = \true;
            // map all `self::STATUS_` constants from status code to reason phrase
            // e.g. `self::STATUS_NOT_FOUND = 404` will be mapped to `404 Not Found`
            $ref = new \ReflectionClass(__CLASS__);
            foreach ($ref->getConstants() as $name => $value) {
                if (!isset(self::$phrasesMap[$value]) && \strpos($name, 'STATUS_') === 0) {
                    self::$phrasesMap[$value] = \ucwords(\strtolower(\str_replace('_', ' ', \substr($name, 7))));
                }
            }
        }
        return isset(self::$phrasesMap[$code]) ? self::$phrasesMap[$code] : '';
    }
    /**
     * [Internal] Parse incoming HTTP protocol message
     *
     * @internal
     * @param string $message
     * @return self
     * @throws \InvalidArgumentException if given $message is not a valid HTTP response message
     */
    public static function parseMessage($message)
    {
        $start = array();
        if (!\preg_match('#^HTTP/(?<version>\d\.\d) (?<status>\d{3})(?: (?<reason>[^\r\n]*+))?[\r]?+\n#m', $message, $start)) {
            throw new \InvalidArgumentException('Unable to parse invalid status-line');
        }
        // only support HTTP/1.1 and HTTP/1.0 requests
        if ($start['version'] !== '1.1' && $start['version'] !== '1.0') {
            throw new \InvalidArgumentException('Received response with invalid protocol version');
        }
        // check number of valid header fields matches number of lines + status line
        $matches = array();
        $n = \preg_match_all(self::REGEX_HEADERS, $message, $matches, \PREG_SET_ORDER);
        if (\substr_count($message, "\n") !== $n + 1) {
            throw new \InvalidArgumentException('Unable to parse invalid response header fields');
        }
        // format all header fields into associative array
        $headers = array();
        foreach ($matches as $match) {
            $headers[$match[1]][] = $match[2];
        }
        return new self((int) $start['status'], $headers, '', $start['version'], isset($start['reason']) ? $start['reason'] : '');
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Message;

use RuntimeException;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\ResponseInterface;
/**
 * The `React\Http\Message\ResponseException` is an `Exception` sub-class that will be used to reject
 * a request promise if the remote server returns a non-success status code
 * (anything but 2xx or 3xx).
 * You can control this behavior via the [`withRejectErrorResponse()` method](#withrejecterrorresponse).
 *
 * The `getCode(): int` method can be used to
 * return the HTTP response status code.
 */
final class ResponseException extends RuntimeException
{
    private $response;
    public function __construct(ResponseInterface $response, $message = null, $code = null, $previous = null)
    {
        if ($message === null) {
            $message = 'HTTP status code ' . $response->getStatusCode() . ' (' . $response->getReasonPhrase() . ')';
        }
        if ($code === null) {
            $code = $response->getStatusCode();
        }
        parent::__construct($message, $code, $previous);
        $this->response = $response;
    }
    /**
     * Access its underlying response object.
     *
     * @return ResponseInterface
     */
    public function getResponse()
    {
        return $this->response;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Message;

use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\ServerRequestInterface;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\StreamInterface;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\UriInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Io\AbstractRequest;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Io\BufferedBody;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Io\HttpBodyStream;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\ReadableStreamInterface;
/**
 * Respresents an incoming server request message.
 *
 * This class implements the
 * [PSR-7 `ServerRequestInterface`](https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface)
 * which extends the
 * [PSR-7 `RequestInterface`](https://www.php-fig.org/psr/psr-7/#32-psrhttpmessagerequestinterface)
 * which in turn extends the
 * [PSR-7 `MessageInterface`](https://www.php-fig.org/psr/psr-7/#31-psrhttpmessagemessageinterface).
 *
 * This is mostly used internally to represent each incoming request message.
 * Likewise, you can also use this class in test cases to test how your web
 * application reacts to certain HTTP requests.
 *
 * > Internally, this implementation builds on top of a base class which is
 *   considered an implementation detail that may change in the future.
 *
 * @see ServerRequestInterface
 */
final class ServerRequest extends AbstractRequest implements ServerRequestInterface
{
    private $attributes = array();
    private $serverParams;
    private $fileParams = array();
    private $cookies = array();
    private $queryParams = array();
    private $parsedBody;
    /**
     * @param string                                         $method       HTTP method for the request.
     * @param string|UriInterface                            $url          URL for the request.
     * @param array<string,string|string[]>                  $headers      Headers for the message.
     * @param string|ReadableStreamInterface|StreamInterface $body         Message body.
     * @param string                                         $version      HTTP protocol version.
     * @param array<string,string>                           $serverParams server-side parameters
     * @throws \InvalidArgumentException for an invalid URL or body
     */
    public function __construct($method, $url, array $headers = array(), $body = '', $version = '1.1', $serverParams = array())
    {
        if (\is_string($body)) {
            $body = new BufferedBody($body);
        } elseif ($body instanceof ReadableStreamInterface && !$body instanceof StreamInterface) {
            $temp = new self($method, '', $headers);
            $size = (int) $temp->getHeaderLine('Content-Length');
            if (\strtolower($temp->getHeaderLine('Transfer-Encoding')) === 'chunked') {
                $size = null;
            }
            $body = new HttpBodyStream($body, $size);
        } elseif (!$body instanceof StreamInterface) {
            throw new \InvalidArgumentException('Invalid server request body given');
        }
        parent::__construct($method, $url, $headers, $body, $version);
        $this->serverParams = $serverParams;
        $query = $this->getUri()->getQuery();
        if ($query !== '') {
            \parse_str($query, $this->queryParams);
        }
        // Multiple cookie headers are not allowed according
        // to https://tools.ietf.org/html/rfc6265#section-5.4
        $cookieHeaders = $this->getHeader("Cookie");
        if (count($cookieHeaders) === 1) {
            $this->cookies = $this->parseCookie($cookieHeaders[0]);
        }
    }
    public function getServerParams()
    {
        return $this->serverParams;
    }
    public function getCookieParams()
    {
        return $this->cookies;
    }
    public function withCookieParams(array $cookies)
    {
        $new = clone $this;
        $new->cookies = $cookies;
        return $new;
    }
    public function getQueryParams()
    {
        return $this->queryParams;
    }
    public function withQueryParams(array $query)
    {
        $new = clone $this;
        $new->queryParams = $query;
        return $new;
    }
    public function getUploadedFiles()
    {
        return $this->fileParams;
    }
    public function withUploadedFiles(array $uploadedFiles)
    {
        $new = clone $this;
        $new->fileParams = $uploadedFiles;
        return $new;
    }
    public function getParsedBody()
    {
        return $this->parsedBody;
    }
    public function withParsedBody($data)
    {
        $new = clone $this;
        $new->parsedBody = $data;
        return $new;
    }
    public function getAttributes()
    {
        return $this->attributes;
    }
    public function getAttribute($name, $default = null)
    {
        if (!\array_key_exists($name, $this->attributes)) {
            return $default;
        }
        return $this->attributes[$name];
    }
    public function withAttribute($name, $value)
    {
        $new = clone $this;
        $new->attributes[$name] = $value;
        return $new;
    }
    public function withoutAttribute($name)
    {
        $new = clone $this;
        unset($new->attributes[$name]);
        return $new;
    }
    /**
     * @param string $cookie
     * @return array
     */
    private function parseCookie($cookie)
    {
        $cookieArray = \explode(';', $cookie);
        $result = array();
        foreach ($cookieArray as $pair) {
            $pair = \trim($pair);
            $nameValuePair = \explode('=', $pair, 2);
            if (\count($nameValuePair) === 2) {
                $key = $nameValuePair[0];
                $value = \urldecode($nameValuePair[1]);
                $result[$key] = $value;
            }
        }
        return $result;
    }
    /**
     * [Internal] Parse incoming HTTP protocol message
     *
     * @internal
     * @param string $message
     * @param array<string,string|int|float> $serverParams
     * @return self
     * @throws \InvalidArgumentException if given $message is not a valid HTTP request message
     */
    public static function parseMessage($message, array $serverParams)
    {
        // parse request line like "GET /path HTTP/1.1"
        $start = array();
        if (!\preg_match('#^(?<method>[^ ]+) (?<target>[^ ]+) HTTP/(?<version>\d\.\d)#m', $message, $start)) {
            throw new \InvalidArgumentException('Unable to parse invalid request-line');
        }
        // only support HTTP/1.1 and HTTP/1.0 requests
        if ($start['version'] !== '1.1' && $start['version'] !== '1.0') {
            throw new \InvalidArgumentException('Received request with invalid protocol version', Response::STATUS_VERSION_NOT_SUPPORTED);
        }
        // check number of valid header fields matches number of lines + request line
        $matches = array();
        $n = \preg_match_all(self::REGEX_HEADERS, $message, $matches, \PREG_SET_ORDER);
        if (\substr_count($message, "\n") !== $n + 1) {
            throw new \InvalidArgumentException('Unable to parse invalid request header fields');
        }
        // format all header fields into associative array
        $host = null;
        $headers = array();
        foreach ($matches as $match) {
            $headers[$match[1]][] = $match[2];
            // match `Host` request header
            if ($host === null && \strtolower($match[1]) === 'host') {
                $host = $match[2];
            }
        }
        // scheme is `http` unless TLS is used
        $scheme = isset($serverParams['HTTPS']) ? 'https://' : 'http://';
        // default host if unset comes from local socket address or defaults to localhost
        $hasHost = $host !== null;
        if ($host === null) {
            $host = isset($serverParams['SERVER_ADDR'], $serverParams['SERVER_PORT']) ? $serverParams['SERVER_ADDR'] . ':' . $serverParams['SERVER_PORT'] : '127.0.0.1';
        }
        if ($start['method'] === 'OPTIONS' && $start['target'] === '*') {
            // support asterisk-form for `OPTIONS *` request line only
            $uri = $scheme . $host;
        } elseif ($start['method'] === 'CONNECT') {
            $parts = \parse_url('tcp://' . $start['target']);
            // check this is a valid authority-form request-target (host:port)
            if (!isset($parts['scheme'], $parts['host'], $parts['port']) || \count($parts) !== 3) {
                throw new \InvalidArgumentException('CONNECT method MUST use authority-form request target');
            }
            $uri = $scheme . $start['target'];
        } else if ($start['target'][0] === '/') {
            $uri = $scheme . $host . $start['target'];
        } else {
            // ensure absolute-form request-target contains a valid URI
            $parts = \parse_url($start['target']);
            // make sure value contains valid host component (IP or hostname), but no fragment
            if (!isset($parts['scheme'], $parts['host']) || $parts['scheme'] !== 'http' || isset($parts['fragment'])) {
                throw new \InvalidArgumentException('Invalid absolute-form request-target');
            }
            $uri = $start['target'];
        }
        $request = new self($start['method'], $uri, $headers, '', $start['version'], $serverParams);
        // only assign request target if it is not in origin-form (happy path for most normal requests)
        if ($start['target'][0] !== '/') {
            $request = $request->withRequestTarget($start['target']);
        }
        if ($hasHost) {
            // Optional Host request header value MUST be valid (host and optional port)
            $parts = \parse_url('http://' . $request->getHeaderLine('Host'));
            // make sure value contains valid host component (IP or hostname)
            if (!$parts || !isset($parts['scheme'], $parts['host'])) {
                $parts = \false;
            }
            // make sure value does not contain any other URI component
            if (\is_array($parts)) {
                unset($parts['scheme'], $parts['host'], $parts['port']);
            }
            if ($parts === \false || $parts) {
                throw new \InvalidArgumentException('Invalid Host header value');
            }
        } elseif (!$hasHost && $start['version'] === '1.1' && $start['method'] !== 'CONNECT') {
            // require Host request header for HTTP/1.1 (except for CONNECT method)
            throw new \InvalidArgumentException('Missing required Host request header');
        } elseif (!$hasHost) {
            // remove default Host request header for HTTP/1.0 when not explicitly given
            $request = $request->withoutHeader('Host');
        }
        // ensure message boundaries are valid according to Content-Length and Transfer-Encoding request headers
        if ($request->hasHeader('Transfer-Encoding')) {
            if (\strtolower($request->getHeaderLine('Transfer-Encoding')) !== 'chunked') {
                throw new \InvalidArgumentException('Only chunked-encoding is allowed for Transfer-Encoding', Response::STATUS_NOT_IMPLEMENTED);
            }
            // Transfer-Encoding: chunked and Content-Length header MUST NOT be used at the same time
            // as per https://tools.ietf.org/html/rfc7230#section-3.3.3
            if ($request->hasHeader('Content-Length')) {
                throw new \InvalidArgumentException('Using both `Transfer-Encoding: chunked` and `Content-Length` is not allowed', Response::STATUS_BAD_REQUEST);
            }
        } elseif ($request->hasHeader('Content-Length')) {
            $string = $request->getHeaderLine('Content-Length');
            if ((string) (int) $string !== $string) {
                // Content-Length value is not an integer or not a single integer
                throw new \InvalidArgumentException('The value of `Content-Length` is not valid', Response::STATUS_BAD_REQUEST);
            }
        }
        return $request;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Message;

use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\UriInterface;
/**
 * Respresents a URI (or URL).
 *
 * This class implements the
 * [PSR-7 `UriInterface`](https://www.php-fig.org/psr/psr-7/#35-psrhttpmessageuriinterface).
 *
 * This is mostly used internally to represent the URI of each HTTP request
 * message for our HTTP client and server implementations. Likewise, you may
 * also use this class with other HTTP implementations and for tests.
 *
 * @see UriInterface
 */
final class Uri implements UriInterface
{
    /** @var string */
    private $scheme = '';
    /** @var string */
    private $userInfo = '';
    /** @var string */
    private $host = '';
    /** @var ?int */
    private $port = null;
    /** @var string */
    private $path = '';
    /** @var string */
    private $query = '';
    /** @var string */
    private $fragment = '';
    /**
     * @param string $uri
     * @throws \InvalidArgumentException if given $uri is invalid
     */
    public function __construct($uri)
    {
        // @codeCoverageIgnoreStart
        if (\PHP_VERSION_ID < 50407 && \strpos($uri, '//') === 0) {
            // @link https://3v4l.org/UrAQP
            $parts = \parse_url('http:' . $uri);
            unset($parts['schema']);
        } else {
            $parts = \parse_url($uri);
        }
        // @codeCoverageIgnoreEnd
        if ($parts === \false || isset($parts['scheme']) && !\preg_match('#^[a-z]+$#i', $parts['scheme']) || isset($parts['host']) && \preg_match('#[\s%+]#', $parts['host'])) {
            throw new \InvalidArgumentException('Invalid URI given');
        }
        if (isset($parts['scheme'])) {
            $this->scheme = \strtolower($parts['scheme']);
        }
        if (isset($parts['user']) || isset($parts['pass'])) {
            $this->userInfo = $this->encode(isset($parts['user']) ? $parts['user'] : '', \PHP_URL_USER) . (isset($parts['pass']) ? ':' . $this->encode($parts['pass'], \PHP_URL_PASS) : '');
        }
        if (isset($parts['host'])) {
            $this->host = \strtolower($parts['host']);
        }
        if (isset($parts['port']) && !($parts['port'] === 80 && $this->scheme === 'http' || $parts['port'] === 443 && $this->scheme === 'https')) {
            $this->port = $parts['port'];
        }
        if (isset($parts['path'])) {
            $this->path = $this->encode($parts['path'], \PHP_URL_PATH);
        }
        if (isset($parts['query'])) {
            $this->query = $this->encode($parts['query'], \PHP_URL_QUERY);
        }
        if (isset($parts['fragment'])) {
            $this->fragment = $this->encode($parts['fragment'], \PHP_URL_FRAGMENT);
        }
    }
    public function getScheme()
    {
        return $this->scheme;
    }
    public function getAuthority()
    {
        if ($this->host === '') {
            return '';
        }
        return ($this->userInfo !== '' ? $this->userInfo . '@' : '') . $this->host . ($this->port !== null ? ':' . $this->port : '');
    }
    public function getUserInfo()
    {
        return $this->userInfo;
    }
    public function getHost()
    {
        return $this->host;
    }
    public function getPort()
    {
        return $this->port;
    }
    public function getPath()
    {
        return $this->path;
    }
    public function getQuery()
    {
        return $this->query;
    }
    public function getFragment()
    {
        return $this->fragment;
    }
    public function withScheme($scheme)
    {
        $scheme = \strtolower($scheme);
        if ($scheme === $this->scheme) {
            return $this;
        }
        if (!\preg_match('#^[a-z]*$#', $scheme)) {
            throw new \InvalidArgumentException('Invalid URI scheme given');
        }
        $new = clone $this;
        $new->scheme = $scheme;
        if ($this->port === 80 && $scheme === 'http' || $this->port === 443 && $scheme === 'https') {
            $new->port = null;
        }
        return $new;
    }
    public function withUserInfo($user, $password = null)
    {
        $userInfo = $this->encode($user, \PHP_URL_USER) . ($password !== null ? ':' . $this->encode($password, \PHP_URL_PASS) : '');
        if ($userInfo === $this->userInfo) {
            return $this;
        }
        $new = clone $this;
        $new->userInfo = $userInfo;
        return $new;
    }
    public function withHost($host)
    {
        $host = \strtolower($host);
        if ($host === $this->host) {
            return $this;
        }
        if (\preg_match('#[\s%+]#', $host) || $host !== '' && \parse_url('http://' . $host, \PHP_URL_HOST) !== $host) {
            throw new \InvalidArgumentException('Invalid URI host given');
        }
        $new = clone $this;
        $new->host = $host;
        return $new;
    }
    public function withPort($port)
    {
        $port = $port === null ? null : (int) $port;
        if ($port === 80 && $this->scheme === 'http' || $port === 443 && $this->scheme === 'https') {
            $port = null;
        }
        if ($port === $this->port) {
            return $this;
        }
        if ($port !== null && ($port < 1 || $port > 0xffff)) {
            throw new \InvalidArgumentException('Invalid URI port given');
        }
        $new = clone $this;
        $new->port = $port;
        return $new;
    }
    public function withPath($path)
    {
        $path = $this->encode($path, \PHP_URL_PATH);
        if ($path === $this->path) {
            return $this;
        }
        $new = clone $this;
        $new->path = $path;
        return $new;
    }
    public function withQuery($query)
    {
        $query = $this->encode($query, \PHP_URL_QUERY);
        if ($query === $this->query) {
            return $this;
        }
        $new = clone $this;
        $new->query = $query;
        return $new;
    }
    public function withFragment($fragment)
    {
        $fragment = $this->encode($fragment, \PHP_URL_FRAGMENT);
        if ($fragment === $this->fragment) {
            return $this;
        }
        $new = clone $this;
        $new->fragment = $fragment;
        return $new;
    }
    public function __toString()
    {
        $uri = '';
        if ($this->scheme !== '') {
            $uri .= $this->scheme . ':';
        }
        $authority = $this->getAuthority();
        if ($authority !== '') {
            $uri .= '//' . $authority;
        }
        if ($authority !== '' && isset($this->path[0]) && $this->path[0] !== '/') {
            $uri .= '/' . $this->path;
        } elseif ($authority === '' && isset($this->path[0]) && $this->path[0] === '/') {
            $uri .= '/' . \ltrim($this->path, '/');
        } else {
            $uri .= $this->path;
        }
        if ($this->query !== '') {
            $uri .= '?' . $this->query;
        }
        if ($this->fragment !== '') {
            $uri .= '#' . $this->fragment;
        }
        return $uri;
    }
    /**
     * @param string $part
     * @param int $component
     * @return string
     */
    private function encode($part, $component)
    {
        return \preg_replace_callback('/(?:[^a-z0-9_\-\.~!\$&\'\(\)\*\+,;=' . ($component === \PHP_URL_PATH ? ':@\/' : ($component === \PHP_URL_QUERY || $component === \PHP_URL_FRAGMENT ? ':@\/\?' : '')) . '%]++|%(?![a-f0-9]{2}))/i', function (array $match) {
            return \rawurlencode($match[0]);
        }, $part);
    }
    /**
     * [Internal] Resolve URI relative to base URI and return new absolute URI
     *
     * @internal
     * @param UriInterface $base
     * @param UriInterface $rel
     * @return UriInterface
     * @throws void
     */
    public static function resolve(UriInterface $base, UriInterface $rel)
    {
        if ($rel->getScheme() !== '') {
            return $rel->getPath() === '' ? $rel : $rel->withPath(self::removeDotSegments($rel->getPath()));
        }
        $reset = \false;
        $new = $base;
        if ($rel->getAuthority() !== '') {
            $reset = \true;
            $userInfo = \explode(':', $rel->getUserInfo(), 2);
            $new = $base->withUserInfo($userInfo[0], isset($userInfo[1]) ? $userInfo[1] : null)->withHost($rel->getHost())->withPort($rel->getPort());
        }
        if ($reset && $rel->getPath() === '') {
            $new = $new->withPath('');
        } elseif (($path = $rel->getPath()) !== '') {
            $start = '';
            if ($path === '' || $path[0] !== '/') {
                $start = $base->getPath();
                if (\substr($start, -1) !== '/') {
                    $start .= '/../';
                }
            }
            $reset = \true;
            $new = $new->withPath(self::removeDotSegments($start . $path));
        }
        if ($reset || $rel->getQuery() !== '') {
            $reset = \true;
            $new = $new->withQuery($rel->getQuery());
        }
        if ($reset || $rel->getFragment() !== '') {
            $new = $new->withFragment($rel->getFragment());
        }
        return $new;
    }
    /**
     * @param string $path
     * @return string
     */
    private static function removeDotSegments($path)
    {
        $segments = array();
        foreach (\explode('/', $path) as $segment) {
            if ($segment === '..') {
                \array_pop($segments);
            } elseif ($segment !== '.' && $segment !== '') {
                $segments[] = $segment;
            }
        }
        return '/' . \implode('/', $segments) . ($path !== '/' && \substr($path, -1) === '/' ? '/' : '');
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Middleware;

use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\ResponseInterface;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\ServerRequestInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Io\HttpBodyStream;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Io\PauseBufferStream;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\PromiseInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\Deferred;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\ReadableStreamInterface;
/**
 * Limits how many next handlers can be executed concurrently.
 *
 * If this middleware is invoked, it will check if the number of pending
 * handlers is below the allowed limit and then simply invoke the next handler
 * and it will return whatever the next handler returns (or throws).
 *
 * If the number of pending handlers exceeds the allowed limit, the request will
 * be queued (and its streaming body will be paused) and it will return a pending
 * promise.
 * Once a pending handler returns (or throws), it will pick the oldest request
 * from this queue and invokes the next handler (and its streaming body will be
 * resumed).
 *
 * The following example shows how this middleware can be used to ensure no more
 * than 10 handlers will be invoked at once:
 *
 * ```php
 * $http = new React\Http\HttpServer(
 *     new React\Http\Middleware\StreamingRequestMiddleware(),
 *     new React\Http\Middleware\LimitConcurrentRequestsMiddleware(10),
 *     $handler
 * );
 * ```
 *
 * Similarly, this middleware is often used in combination with the
 * [`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware) (see below)
 * to limit the total number of requests that can be buffered at once:
 *
 * ```php
 * $http = new React\Http\HttpServer(
 *     new React\Http\Middleware\StreamingRequestMiddleware(),
 *     new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers
 *     new React\Http\Middleware\RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request
 *     new React\Http\Middleware\RequestBodyParserMiddleware(),
 *     $handler
 * );
 * ```
 *
 * More sophisticated examples include limiting the total number of requests
 * that can be buffered at once and then ensure the actual request handler only
 * processes one request after another without any concurrency:
 *
 * ```php
 * $http = new React\Http\HttpServer(
 *     new React\Http\Middleware\StreamingRequestMiddleware(),
 *     new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers
 *     new React\Http\Middleware\RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request
 *     new React\Http\Middleware\RequestBodyParserMiddleware(),
 *     new React\Http\Middleware\LimitConcurrentRequestsMiddleware(1), // only execute 1 handler (no concurrency)
 *     $handler
 * );
 * ```
 *
 * @see RequestBodyBufferMiddleware
 */
final class LimitConcurrentRequestsMiddleware
{
    private $limit;
    private $pending = 0;
    private $queue = array();
    /**
     * @param int $limit Maximum amount of concurrent requests handled.
     *
     * For example when $limit is set to 10, 10 requests will flow to $next
     * while more incoming requests have to wait until one is done.
     */
    public function __construct($limit)
    {
        $this->limit = $limit;
    }
    public function __invoke(ServerRequestInterface $request, $next)
    {
        // happy path: simply invoke next request handler if we're below limit
        if ($this->pending < $this->limit) {
            ++$this->pending;
            try {
                $response = $next($request);
            } catch (\Exception $e) {
                $this->processQueue();
                throw $e;
            } catch (\Throwable $e) {
                // @codeCoverageIgnoreStart
                // handle Errors just like Exceptions (PHP 7+ only)
                $this->processQueue();
                throw $e;
                // @codeCoverageIgnoreEnd
            }
            // happy path: if next request handler returned immediately,
            // we can simply try to invoke the next queued request
            if ($response instanceof ResponseInterface) {
                $this->processQueue();
                return $response;
            }
            // if the next handler returns a pending promise, we have to
            // await its resolution before invoking next queued request
            return $this->await(Promise\resolve($response));
        }
        // if we reach this point, then this request will need to be queued
        // check if the body is streaming, in which case we need to buffer everything
        $body = $request->getBody();
        if ($body instanceof ReadableStreamInterface) {
            // pause actual body to stop emitting data until the handler is called
            $size = $body->getSize();
            $body = new PauseBufferStream($body);
            $body->pauseImplicit();
            // replace with buffering body to ensure any readable events will be buffered
            $request = $request->withBody(new HttpBodyStream($body, $size));
        }
        // get next queue position
        $queue =& $this->queue;
        $queue[] = null;
        \end($queue);
        $id = \key($queue);
        $deferred = new Deferred(function ($_, $reject) use (&$queue, $id) {
            // queued promise cancelled before its next handler is invoked
            // remove from queue and reject explicitly
            unset($queue[$id]);
            $reject(new \RuntimeException('Cancelled queued next handler'));
        });
        // queue request and process queue if pending does not exceed limit
        $queue[$id] = $deferred;
        $pending =& $this->pending;
        $that = $this;
        return $deferred->promise()->then(function () use ($request, $next, $body, &$pending, $that) {
            // invoke next request handler
            ++$pending;
            try {
                $response = $next($request);
            } catch (\Exception $e) {
                $that->processQueue();
                throw $e;
            } catch (\Throwable $e) {
                // @codeCoverageIgnoreStart
                // handle Errors just like Exceptions (PHP 7+ only)
                $that->processQueue();
                throw $e;
                // @codeCoverageIgnoreEnd
            }
            // resume readable stream and replay buffered events
            if ($body instanceof PauseBufferStream) {
                $body->resumeImplicit();
            }
            // if the next handler returns a pending promise, we have to
            // await its resolution before invoking next queued request
            return $that->await(Promise\resolve($response));
        });
    }
    /**
     * @internal
     * @param PromiseInterface $promise
     * @return PromiseInterface
     */
    public function await(PromiseInterface $promise)
    {
        $that = $this;
        return $promise->then(function ($response) use ($that) {
            $that->processQueue();
            return $response;
        }, function ($error) use ($that) {
            $that->processQueue();
            return Promise\reject($error);
        });
    }
    /**
     * @internal
     */
    public function processQueue()
    {
        // skip if we're still above concurrency limit or there's no queued request waiting
        if (--$this->pending >= $this->limit || !$this->queue) {
            return;
        }
        $first = \reset($this->queue);
        unset($this->queue[key($this->queue)]);
        $first->resolve(null);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Middleware;

use OverflowException;
use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\ServerRequestInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Io\BufferedBody;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Io\IniUtil;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\Promise;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\ReadableStreamInterface;
final class RequestBodyBufferMiddleware
{
    private $sizeLimit;
    /**
     * @param int|string|null $sizeLimit Either an int with the max request body size
     *                                   in bytes or an ini like size string
     *                                   or null to use post_max_size from PHP's
     *                                   configuration. (Note that the value from
     *                                   the CLI configuration will be used.)
     */
    public function __construct($sizeLimit = null)
    {
        if ($sizeLimit === null) {
            $sizeLimit = \ini_get('post_max_size');
        }
        $this->sizeLimit = IniUtil::iniSizeToBytes($sizeLimit);
    }
    public function __invoke(ServerRequestInterface $request, $next)
    {
        $body = $request->getBody();
        $size = $body->getSize();
        // happy path: skip if body is known to be empty (or is already buffered)
        if ($size === 0 || !$body instanceof ReadableStreamInterface || !$body->isReadable()) {
            // replace with empty body if body is streaming (or buffered size exceeds limit)
            if ($body instanceof ReadableStreamInterface || $size > $this->sizeLimit) {
                $request = $request->withBody(new BufferedBody(''));
            }
            return $next($request);
        }
        // request body of known size exceeding limit
        $sizeLimit = $this->sizeLimit;
        if ($size > $this->sizeLimit) {
            $sizeLimit = 0;
        }
        /** @var ?\Closure $closer */
        $closer = null;
        return new Promise(function ($resolve, $reject) use ($body, &$closer, $sizeLimit, $request, $next) {
            // buffer request body data in memory, discard but keep buffering if limit is reached
            $buffer = '';
            $bufferer = null;
            $body->on('data', $bufferer = function ($data) use (&$buffer, $sizeLimit, $body, &$bufferer) {
                $buffer .= $data;
                // On buffer overflow keep the request body stream in,
                // but ignore the contents and wait for the close event
                // before passing the request on to the next middleware.
                if (isset($buffer[$sizeLimit])) {
                    assert($bufferer instanceof \Closure);
                    $body->removeListener('data', $bufferer);
                    $bufferer = null;
                    $buffer = '';
                }
            });
            // call $next with current buffer and resolve or reject with its results
            $body->on('close', $closer = function () use (&$buffer, $request, $resolve, $reject, $next) {
                try {
                    // resolve with result of next handler
                    $resolve($next($request->withBody(new BufferedBody($buffer))));
                } catch (\Exception $e) {
                    $reject($e);
                } catch (\Throwable $e) {
                    // @codeCoverageIgnoreStart
                    // reject Errors just like Exceptions (PHP 7+)
                    $reject($e);
                    // @codeCoverageIgnoreEnd
                }
            });
            // reject buffering if body emits error
            $body->on('error', function (\Exception $e) use ($reject, $body, $closer) {
                // remove close handler to avoid resolving, then close and reject
                assert($closer instanceof \Closure);
                $body->removeListener('close', $closer);
                $body->close();
                $reject(new \RuntimeException('Error while buffering request body: ' . $e->getMessage(), $e->getCode(), $e));
            });
        }, function () use ($body, &$closer) {
            // cancelled buffering: remove close handler to avoid resolving, then close and reject
            assert($closer instanceof \Closure);
            $body->removeListener('close', $closer);
            $body->close();
            throw new \RuntimeException('Cancelled buffering request body');
        });
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Middleware;

use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\ServerRequestInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Http\Io\MultipartParser;
final class RequestBodyParserMiddleware
{
    private $multipart;
    /**
     * @param int|string|null $uploadMaxFilesize
     * @param int|null $maxFileUploads
     */
    public function __construct($uploadMaxFilesize = null, $maxFileUploads = null)
    {
        $this->multipart = new MultipartParser($uploadMaxFilesize, $maxFileUploads);
    }
    public function __invoke(ServerRequestInterface $request, $next)
    {
        $type = \strtolower($request->getHeaderLine('Content-Type'));
        list($type) = \explode(';', $type);
        if ($type === 'application/x-www-form-urlencoded') {
            return $next($this->parseFormUrlencoded($request));
        }
        if ($type === 'multipart/form-data') {
            return $next($this->multipart->parse($request));
        }
        return $next($request);
    }
    private function parseFormUrlencoded(ServerRequestInterface $request)
    {
        // parse string into array structure
        // ignore warnings due to excessive data structures (max_input_vars and max_input_nesting_level)
        $ret = array();
        @\parse_str((string) $request->getBody(), $ret);
        return $request->withParsedBody($ret);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http\Middleware;

use NightwatchAgent_kden27khxA4QoEfj\Psr\Http\Message\ServerRequestInterface;
/**
 * Process incoming requests with a streaming request body (without buffering).
 *
 * This allows you to process requests of any size without buffering the request
 * body in memory. Instead, it will represent the request body as a
 * [`ReadableStreamInterface`](https://github.com/reactphp/stream#readablestreaminterface)
 * that emit chunks of incoming data as it is received:
 *
 * ```php
 * $http = new React\Http\HttpServer(
 *     new React\Http\Middleware\StreamingRequestMiddleware(),
 *     function (Psr\Http\Message\ServerRequestInterface $request) {
 *         $body = $request->getBody();
 *         assert($body instanceof Psr\Http\Message\StreamInterface);
 *         assert($body instanceof React\Stream\ReadableStreamInterface);
 *
 *         return new React\Promise\Promise(function ($resolve) use ($body) {
 *             $bytes = 0;
 *             $body->on('data', function ($chunk) use (&$bytes) {
 *                 $bytes += \count($chunk);
 *             });
 *             $body->on('close', function () use (&$bytes, $resolve) {
 *                 $resolve(new React\Http\Response(
 *                     200,
 *                     [],
 *                     "Received $bytes bytes\n"
 *                 ));
 *             });
 *         });
 *     }
 * );
 * ```
 *
 * See also [streaming incoming request](../../README.md#streaming-incoming-request)
 * for more details.
 *
 * Additionally, this middleware can be used in combination with the
 * [`LimitConcurrentRequestsMiddleware`](#limitconcurrentrequestsmiddleware) and
 * [`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware) (see below)
 * to explicitly configure the total number of requests that can be handled at
 * once:
 *
 * ```php
 * $http = new React\Http\HttpServer(
 *     new React\Http\Middleware\StreamingRequestMiddleware(),
 *     new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers
 *     new React\Http\Middleware\RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request
 *     new React\Http\Middleware\RequestBodyParserMiddleware(),
 *     $handler
 * );
 * ```
 *
 * > Internally, this class is used as a "marker" to not trigger the default
 *   request buffering behavior in the `HttpServer`. It does not implement any logic
 *   on its own.
 */
final class StreamingRequestMiddleware
{
    public function __invoke(ServerRequestInterface $request, $next)
    {
        return $next($request);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Http;

// Deprecated `Server` is an alias for new `HttpServer` to ensure existing code continues to work as-is.
\class_alias(__NAMESPACE__ . '\HttpServer', __NAMESPACE__ . '\Server', \true);
// Aid static analysis and IDE autocompletion about this deprecation,
// but don't actually execute during runtime because `HttpServer` is final.
if (!\class_exists(__NAMESPACE__ . '\Server', \false)) {
    /**
     * @deprecated 1.5.0 See HttpServer instead
     * @see HttpServer
     */
    final class Server extends HttpServer
    {
    }
}
The MIT License (MIT)

Copyright (c) 2012 Jan Sorgalla, Christian Lück, Cees-Jan Kiewiet, Chris Boden

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Promise;

/**
 * @template T
 */
final class Deferred
{
    /**
     * @var PromiseInterface<T>
     */
    private $promise;
    /** @var callable(T):void */
    private $resolveCallback;
    /** @var callable(\Throwable):void */
    private $rejectCallback;
    /**
     * @param (callable(callable(T):void,callable(\Throwable):void):void)|null $canceller
     */
    public function __construct(?callable $canceller = null)
    {
        $this->promise = new Promise(function ($resolve, $reject): void {
            $this->resolveCallback = $resolve;
            $this->rejectCallback = $reject;
        }, $canceller);
    }
    /**
     * @return PromiseInterface<T>
     */
    public function promise(): PromiseInterface
    {
        return $this->promise;
    }
    /**
     * @param T $value
     */
    public function resolve($value): void
    {
        ($this->resolveCallback)($value);
    }
    public function reject(\Throwable $reason): void
    {
        ($this->rejectCallback)($reason);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Promise\Exception;

/**
 * Represents an exception that is a composite of one or more other exceptions.
 *
 * This exception is useful in situations where a promise must be rejected
 * with multiple exceptions. It is used for example to reject the returned
 * promise from `some()` and `any()` when too many input promises reject.
 */
class CompositeException extends \Exception
{
    /** @var \Throwable[] */
    private $throwables;
    /** @param \Throwable[] $throwables */
    public function __construct(array $throwables, string $message = '', int $code = 0, ?\Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
        $this->throwables = $throwables;
    }
    /**
     * @return \Throwable[]
     */
    public function getThrowables(): array
    {
        return $this->throwables;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Promise\Exception;

class LengthException extends \LengthException
{
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Promise\Internal;

/**
 * @internal
 */
final class CancellationQueue
{
    /** @var bool */
    private $started = \false;
    /** @var object[] */
    private $queue = [];
    public function __invoke(): void
    {
        if ($this->started) {
            return;
        }
        $this->started = \true;
        $this->drain();
    }
    /**
     * @param mixed $cancellable
     */
    public function enqueue($cancellable): void
    {
        if (!\is_object($cancellable) || !\method_exists($cancellable, 'then') || !\method_exists($cancellable, 'cancel')) {
            return;
        }
        $length = \array_push($this->queue, $cancellable);
        if ($this->started && 1 === $length) {
            $this->drain();
        }
    }
    private function drain(): void
    {
        for ($i = \key($this->queue); isset($this->queue[$i]); $i++) {
            $cancellable = $this->queue[$i];
            assert(\method_exists($cancellable, 'cancel'));
            $exception = null;
            try {
                $cancellable->cancel();
            } catch (\Throwable $exception) {
            }
            unset($this->queue[$i]);
            if ($exception) {
                throw $exception;
            }
        }
        $this->queue = [];
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Promise\Internal;

use NightwatchAgent_kden27khxA4QoEfj\React\Promise\PromiseInterface;
use function NightwatchAgent_kden27khxA4QoEfj\React\Promise\resolve;
/**
 * @internal
 *
 * @template T
 * @template-implements PromiseInterface<T>
 */
final class FulfilledPromise implements PromiseInterface
{
    /** @var T */
    private $value;
    /**
     * @param T $value
     * @throws \InvalidArgumentException
     */
    public function __construct($value = null)
    {
        if ($value instanceof PromiseInterface) {
            throw new \InvalidArgumentException('You cannot create React\Promise\FulfilledPromise with a promise. Use React\Promise\resolve($promiseOrValue) instead.');
        }
        $this->value = $value;
    }
    /**
     * @template TFulfilled
     * @param ?(callable((T is void ? null : T)): (PromiseInterface<TFulfilled>|TFulfilled)) $onFulfilled
     * @return PromiseInterface<($onFulfilled is null ? T : TFulfilled)>
     */
    public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface
    {
        if (null === $onFulfilled) {
            return $this;
        }
        try {
            /**
             * @var PromiseInterface<T>|T $result
             */
            $result = $onFulfilled($this->value);
            return resolve($result);
        } catch (\Throwable $exception) {
            return new RejectedPromise($exception);
        }
    }
    public function catch(callable $onRejected): PromiseInterface
    {
        return $this;
    }
    public function finally(callable $onFulfilledOrRejected): PromiseInterface
    {
        return $this->then(function ($value) use ($onFulfilledOrRejected): PromiseInterface {
            /** @var T $value */
            return resolve($onFulfilledOrRejected())->then(function () use ($value) {
                return $value;
            });
        });
    }
    public function cancel(): void
    {
    }
    /**
     * @deprecated 3.0.0 Use `catch()` instead
     * @see self::catch()
     */
    public function otherwise(callable $onRejected): PromiseInterface
    {
        return $this->catch($onRejected);
    }
    /**
     * @deprecated 3.0.0 Use `finally()` instead
     * @see self::finally()
     */
    public function always(callable $onFulfilledOrRejected): PromiseInterface
    {
        return $this->finally($onFulfilledOrRejected);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Promise\Internal;

use NightwatchAgent_kden27khxA4QoEfj\React\Promise\PromiseInterface;
use function NightwatchAgent_kden27khxA4QoEfj\React\Promise\_checkTypehint;
use function NightwatchAgent_kden27khxA4QoEfj\React\Promise\resolve;
use function NightwatchAgent_kden27khxA4QoEfj\React\Promise\set_rejection_handler;
/**
 * @internal
 *
 * @template-implements PromiseInterface<never>
 */
final class RejectedPromise implements PromiseInterface
{
    /** @var \Throwable */
    private $reason;
    /** @var bool */
    private $handled = \false;
    /**
     * @param \Throwable $reason
     */
    public function __construct(\Throwable $reason)
    {
        $this->reason = $reason;
    }
    /** @throws void */
    public function __destruct()
    {
        if ($this->handled) {
            return;
        }
        $handler = set_rejection_handler(null);
        if ($handler === null) {
            $message = 'Unhandled promise rejection with ' . $this->reason;
            \error_log($message);
            return;
        }
        try {
            $handler($this->reason);
        } catch (\Throwable $e) {
            \preg_match('/^([^:\s]++)(.*+)$/sm', (string) $e, $match);
            \assert(isset($match[1], $match[2]));
            $message = 'Fatal error: Uncaught ' . $match[1] . ' from unhandled promise rejection handler' . $match[2];
            \error_log($message);
            exit(255);
        }
    }
    /**
     * @template TRejected
     * @param ?callable $onFulfilled
     * @param ?(callable(\Throwable): (PromiseInterface<TRejected>|TRejected)) $onRejected
     * @return PromiseInterface<($onRejected is null ? never : TRejected)>
     */
    public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface
    {
        if (null === $onRejected) {
            return $this;
        }
        $this->handled = \true;
        try {
            return resolve($onRejected($this->reason));
        } catch (\Throwable $exception) {
            return new RejectedPromise($exception);
        }
    }
    /**
     * @template TThrowable of \Throwable
     * @template TRejected
     * @param callable(TThrowable): (PromiseInterface<TRejected>|TRejected) $onRejected
     * @return PromiseInterface<TRejected>
     */
    public function catch(callable $onRejected): PromiseInterface
    {
        if (!_checkTypehint($onRejected, $this->reason)) {
            return $this;
        }
        /**
         * @var callable(\Throwable):(PromiseInterface<TRejected>|TRejected) $onRejected
         */
        return $this->then(null, $onRejected);
    }
    public function finally(callable $onFulfilledOrRejected): PromiseInterface
    {
        return $this->then(null, function (\Throwable $reason) use ($onFulfilledOrRejected): PromiseInterface {
            return resolve($onFulfilledOrRejected())->then(function () use ($reason): PromiseInterface {
                return new RejectedPromise($reason);
            });
        });
    }
    public function cancel(): void
    {
        $this->handled = \true;
    }
    /**
     * @deprecated 3.0.0 Use `catch()` instead
     * @see self::catch()
     */
    public function otherwise(callable $onRejected): PromiseInterface
    {
        return $this->catch($onRejected);
    }
    /**
     * @deprecated 3.0.0 Use `always()` instead
     * @see self::always()
     */
    public function always(callable $onFulfilledOrRejected): PromiseInterface
    {
        return $this->finally($onFulfilledOrRejected);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Promise;

use NightwatchAgent_kden27khxA4QoEfj\React\Promise\Internal\RejectedPromise;
/**
 * @template T
 * @template-implements PromiseInterface<T>
 */
final class Promise implements PromiseInterface
{
    /** @var (callable(callable(T):void,callable(\Throwable):void):void)|null */
    private $canceller;
    /** @var ?PromiseInterface<T> */
    private $result;
    /** @var list<callable(PromiseInterface<T>):void> */
    private $handlers = [];
    /** @var int */
    private $requiredCancelRequests = 0;
    /** @var bool */
    private $cancelled = \false;
    /**
     * @param callable(callable(T):void,callable(\Throwable):void):void $resolver
     * @param (callable(callable(T):void,callable(\Throwable):void):void)|null $canceller
     */
    public function __construct(callable $resolver, ?callable $canceller = null)
    {
        $this->canceller = $canceller;
        // Explicitly overwrite arguments with null values before invoking
        // resolver function. This ensure that these arguments do not show up
        // in the stack trace in PHP 7+ only.
        $cb = $resolver;
        $resolver = $canceller = null;
        $this->call($cb);
    }
    public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface
    {
        if (null !== $this->result) {
            return $this->result->then($onFulfilled, $onRejected);
        }
        if (null === $this->canceller) {
            return new static($this->resolver($onFulfilled, $onRejected));
        }
        // This promise has a canceller, so we create a new child promise which
        // has a canceller that invokes the parent canceller if all other
        // followers are also cancelled. We keep a reference to this promise
        // instance for the static canceller function and clear this to avoid
        // keeping a cyclic reference between parent and follower.
        $parent = $this;
        ++$parent->requiredCancelRequests;
        return new static($this->resolver($onFulfilled, $onRejected), static function () use (&$parent): void {
            assert($parent instanceof self);
            --$parent->requiredCancelRequests;
            if ($parent->requiredCancelRequests <= 0) {
                $parent->cancel();
            }
            $parent = null;
        });
    }
    /**
     * @template TThrowable of \Throwable
     * @template TRejected
     * @param callable(TThrowable): (PromiseInterface<TRejected>|TRejected) $onRejected
     * @return PromiseInterface<T|TRejected>
     */
    public function catch(callable $onRejected): PromiseInterface
    {
        return $this->then(null, static function (\Throwable $reason) use ($onRejected) {
            if (!_checkTypehint($onRejected, $reason)) {
                return new RejectedPromise($reason);
            }
            /**
             * @var callable(\Throwable):(PromiseInterface<TRejected>|TRejected) $onRejected
             */
            return $onRejected($reason);
        });
    }
    public function finally(callable $onFulfilledOrRejected): PromiseInterface
    {
        return $this->then(static function ($value) use ($onFulfilledOrRejected): PromiseInterface {
            /** @var T $value */
            return resolve($onFulfilledOrRejected())->then(function () use ($value) {
                return $value;
            });
        }, static function (\Throwable $reason) use ($onFulfilledOrRejected): PromiseInterface {
            return resolve($onFulfilledOrRejected())->then(function () use ($reason): RejectedPromise {
                return new RejectedPromise($reason);
            });
        });
    }
    public function cancel(): void
    {
        $this->cancelled = \true;
        $canceller = $this->canceller;
        $this->canceller = null;
        $parentCanceller = null;
        if (null !== $this->result) {
            // Forward cancellation to rejected promise to avoid reporting unhandled rejection
            if ($this->result instanceof RejectedPromise) {
                $this->result->cancel();
            }
            // Go up the promise chain and reach the top most promise which is
            // itself not following another promise
            $root = $this->unwrap($this->result);
            // Return if the root promise is already resolved or a
            // FulfilledPromise or RejectedPromise
            if (!$root instanceof self || null !== $root->result) {
                return;
            }
            $root->requiredCancelRequests--;
            if ($root->requiredCancelRequests <= 0) {
                $parentCanceller = [$root, 'cancel'];
            }
        }
        if (null !== $canceller) {
            $this->call($canceller);
        }
        // For BC, we call the parent canceller after our own canceller
        if ($parentCanceller) {
            $parentCanceller();
        }
    }
    /**
     * @deprecated 3.0.0 Use `catch()` instead
     * @see self::catch()
     */
    public function otherwise(callable $onRejected): PromiseInterface
    {
        return $this->catch($onRejected);
    }
    /**
     * @deprecated 3.0.0 Use `finally()` instead
     * @see self::finally()
     */
    public function always(callable $onFulfilledOrRejected): PromiseInterface
    {
        return $this->finally($onFulfilledOrRejected);
    }
    private function resolver(?callable $onFulfilled = null, ?callable $onRejected = null): callable
    {
        return function (callable $resolve, callable $reject) use ($onFulfilled, $onRejected): void {
            $this->handlers[] = static function (PromiseInterface $promise) use ($onFulfilled, $onRejected, $resolve, $reject): void {
                $promise = $promise->then($onFulfilled, $onRejected);
                if ($promise instanceof self && $promise->result === null) {
                    $promise->handlers[] = static function (PromiseInterface $promise) use ($resolve, $reject): void {
                        $promise->then($resolve, $reject);
                    };
                } else {
                    $promise->then($resolve, $reject);
                }
            };
        };
    }
    private function reject(\Throwable $reason): void
    {
        if (null !== $this->result) {
            return;
        }
        $this->settle(reject($reason));
    }
    /**
     * @param PromiseInterface<T> $result
     */
    private function settle(PromiseInterface $result): void
    {
        $result = $this->unwrap($result);
        if ($result === $this) {
            $result = new RejectedPromise(new \LogicException('Cannot resolve a promise with itself.'));
        }
        if ($result instanceof self) {
            $result->requiredCancelRequests++;
        } else {
            // Unset canceller only when not following a pending promise
            $this->canceller = null;
        }
        $handlers = $this->handlers;
        $this->handlers = [];
        $this->result = $result;
        foreach ($handlers as $handler) {
            $handler($result);
        }
        // Forward cancellation to rejected promise to avoid reporting unhandled rejection
        if ($this->cancelled && $result instanceof RejectedPromise) {
            $result->cancel();
        }
    }
    /**
     * @param PromiseInterface<T> $promise
     * @return PromiseInterface<T>
     */
    private function unwrap(PromiseInterface $promise): PromiseInterface
    {
        while ($promise instanceof self && null !== $promise->result) {
            /** @var PromiseInterface<T> $promise */
            $promise = $promise->result;
        }
        return $promise;
    }
    /**
     * @param callable(callable(mixed):void,callable(\Throwable):void):void $cb
     */
    private function call(callable $cb): void
    {
        // Explicitly overwrite argument with null value. This ensure that this
        // argument does not show up in the stack trace in PHP 7+ only.
        $callback = $cb;
        $cb = null;
        // Use reflection to inspect number of arguments expected by this callback.
        // We did some careful benchmarking here: Using reflection to avoid unneeded
        // function arguments is actually faster than blindly passing them.
        // Also, this helps avoiding unnecessary function arguments in the call stack
        // if the callback creates an Exception (creating garbage cycles).
        if (\is_array($callback)) {
            $ref = new \ReflectionMethod($callback[0], $callback[1]);
        } elseif (\is_object($callback) && !$callback instanceof \Closure) {
            $ref = new \ReflectionMethod($callback, '__invoke');
        } else {
            assert($callback instanceof \Closure || \is_string($callback));
            $ref = new \ReflectionFunction($callback);
        }
        $args = $ref->getNumberOfParameters();
        try {
            if ($args === 0) {
                $callback();
            } else {
                // Keep references to this promise instance for the static resolve/reject functions.
                // By using static callbacks that are not bound to this instance
                // and passing the target promise instance by reference, we can
                // still execute its resolving logic and still clear this
                // reference when settling the promise. This helps avoiding
                // garbage cycles if any callback creates an Exception.
                // These assumptions are covered by the test suite, so if you ever feel like
                // refactoring this, go ahead, any alternative suggestions are welcome!
                $target =& $this;
                $callback(static function ($value) use (&$target): void {
                    if ($target !== null) {
                        $target->settle(resolve($value));
                        $target = null;
                    }
                }, static function (\Throwable $reason) use (&$target): void {
                    if ($target !== null) {
                        $target->reject($reason);
                        $target = null;
                    }
                });
            }
        } catch (\Throwable $e) {
            $target = null;
            $this->reject($e);
        }
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Promise;

/**
 * @template-covariant T
 */
interface PromiseInterface
{
    /**
     * Transforms a promise's value by applying a function to the promise's fulfillment
     * or rejection value. Returns a new promise for the transformed result.
     *
     * The `then()` method registers new fulfilled and rejection handlers with a promise
     * (all parameters are optional):
     *
     *  * `$onFulfilled` will be invoked once the promise is fulfilled and passed
     *     the result as the first argument.
     *  * `$onRejected` will be invoked once the promise is rejected and passed the
     *     reason as the first argument.
     *
     * It returns a new promise that will fulfill with the return value of either
     * `$onFulfilled` or `$onRejected`, whichever is called, or will reject with
     * the thrown exception if either throws.
     *
     * A promise makes the following guarantees about handlers registered in
     * the same call to `then()`:
     *
     *  1. Only one of `$onFulfilled` or `$onRejected` will be called,
     *      never both.
     *  2. `$onFulfilled` and `$onRejected` will never be called more
     *      than once.
     *
     * @template TFulfilled
     * @template TRejected
     * @param ?(callable((T is void ? null : T)): (PromiseInterface<TFulfilled>|TFulfilled)) $onFulfilled
     * @param ?(callable(\Throwable): (PromiseInterface<TRejected>|TRejected)) $onRejected
     * @return PromiseInterface<($onRejected is null ? ($onFulfilled is null ? T : TFulfilled) : ($onFulfilled is null ? T|TRejected : TFulfilled|TRejected))>
     */
    public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface;
    /**
     * Registers a rejection handler for promise. It is a shortcut for:
     *
     * ```php
     * $promise->then(null, $onRejected);
     * ```
     *
     * Additionally, you can type hint the `$reason` argument of `$onRejected` to catch
     * only specific errors.
     *
     * @template TThrowable of \Throwable
     * @template TRejected
     * @param callable(TThrowable): (PromiseInterface<TRejected>|TRejected) $onRejected
     * @return PromiseInterface<T|TRejected>
     */
    public function catch(callable $onRejected): PromiseInterface;
    /**
     * Allows you to execute "cleanup" type tasks in a promise chain.
     *
     * It arranges for `$onFulfilledOrRejected` to be called, with no arguments,
     * when the promise is either fulfilled or rejected.
     *
     * * If `$promise` fulfills, and `$onFulfilledOrRejected` returns successfully,
     *    `$newPromise` will fulfill with the same value as `$promise`.
     * * If `$promise` fulfills, and `$onFulfilledOrRejected` throws or returns a
     *    rejected promise, `$newPromise` will reject with the thrown exception or
     *    rejected promise's reason.
     * * If `$promise` rejects, and `$onFulfilledOrRejected` returns successfully,
     *    `$newPromise` will reject with the same reason as `$promise`.
     * * If `$promise` rejects, and `$onFulfilledOrRejected` throws or returns a
     *    rejected promise, `$newPromise` will reject with the thrown exception or
     *    rejected promise's reason.
     *
     * `finally()` behaves similarly to the synchronous finally statement. When combined
     * with `catch()`, `finally()` allows you to write code that is similar to the familiar
     * synchronous catch/finally pair.
     *
     * Consider the following synchronous code:
     *
     * ```php
     * try {
     *     return doSomething();
     * } catch(\Exception $e) {
     *     return handleError($e);
     * } finally {
     *     cleanup();
     * }
     * ```
     *
     * Similar asynchronous code (with `doSomething()` that returns a promise) can be
     * written:
     *
     * ```php
     * return doSomething()
     *     ->catch('handleError')
     *     ->finally('cleanup');
     * ```
     *
     * @param callable(): (void|PromiseInterface<void>) $onFulfilledOrRejected
     * @return PromiseInterface<T>
     */
    public function finally(callable $onFulfilledOrRejected): PromiseInterface;
    /**
     * The `cancel()` method notifies the creator of the promise that there is no
     * further interest in the results of the operation.
     *
     * Once a promise is settled (either fulfilled or rejected), calling `cancel()` on
     * a promise has no effect.
     *
     * @return void
     */
    public function cancel(): void;
    /**
     * [Deprecated] Registers a rejection handler for a promise.
     *
     * This method continues to exist only for BC reasons and to ease upgrading
     * between versions. It is an alias for:
     *
     * ```php
     * $promise->catch($onRejected);
     * ```
     *
     * @template TThrowable of \Throwable
     * @template TRejected
     * @param callable(TThrowable): (PromiseInterface<TRejected>|TRejected) $onRejected
     * @return PromiseInterface<T|TRejected>
     * @deprecated 3.0.0 Use catch() instead
     * @see self::catch()
     */
    public function otherwise(callable $onRejected): PromiseInterface;
    /**
     * [Deprecated] Allows you to execute "cleanup" type tasks in a promise chain.
     *
     * This method continues to exist only for BC reasons and to ease upgrading
     * between versions. It is an alias for:
     *
     * ```php
     * $promise->finally($onFulfilledOrRejected);
     * ```
     *
     * @param callable(): (void|PromiseInterface<void>) $onFulfilledOrRejected
     * @return PromiseInterface<T>
     * @deprecated 3.0.0 Use finally() instead
     * @see self::finally()
     */
    public function always(callable $onFulfilledOrRejected): PromiseInterface;
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Promise;

use NightwatchAgent_kden27khxA4QoEfj\React\Promise\Exception\CompositeException;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\Internal\FulfilledPromise;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\Internal\RejectedPromise;
/**
 * Creates a promise for the supplied `$promiseOrValue`.
 *
 * If `$promiseOrValue` is a value, it will be the resolution value of the
 * returned promise.
 *
 * If `$promiseOrValue` is a thenable (any object that provides a `then()` method),
 * a trusted promise that follows the state of the thenable is returned.
 *
 * If `$promiseOrValue` is a promise, it will be returned as is.
 *
 * @template T
 * @param PromiseInterface<T>|T $promiseOrValue
 * @return PromiseInterface<T>
 */
function resolve($promiseOrValue): PromiseInterface
{
    if ($promiseOrValue instanceof PromiseInterface) {
        return $promiseOrValue;
    }
    if (\is_object($promiseOrValue) && \method_exists($promiseOrValue, 'then')) {
        $canceller = null;
        if (\method_exists($promiseOrValue, 'cancel')) {
            $canceller = [$promiseOrValue, 'cancel'];
            assert(\is_callable($canceller));
        }
        /** @var Promise<T> */
        return new Promise(function (callable $resolve, callable $reject) use ($promiseOrValue): void {
            $promiseOrValue->then($resolve, $reject);
        }, $canceller);
    }
    return new FulfilledPromise($promiseOrValue);
}
/**
 * Creates a rejected promise for the supplied `$reason`.
 *
 * If `$reason` is a value, it will be the rejection value of the
 * returned promise.
 *
 * If `$reason` is a promise, its completion value will be the rejected
 * value of the returned promise.
 *
 * This can be useful in situations where you need to reject a promise without
 * throwing an exception. For example, it allows you to propagate a rejection with
 * the value of another promise.
 *
 * @return PromiseInterface<never>
 */
function reject(\Throwable $reason): PromiseInterface
{
    return new RejectedPromise($reason);
}
/**
 * Returns a promise that will resolve only once all the items in
 * `$promisesOrValues` have resolved. The resolution value of the returned promise
 * will be an array containing the resolution values of each of the items in
 * `$promisesOrValues`.
 *
 * @template T
 * @param iterable<PromiseInterface<T>|T> $promisesOrValues
 * @return PromiseInterface<array<T>>
 */
function all(iterable $promisesOrValues): PromiseInterface
{
    $cancellationQueue = new Internal\CancellationQueue();
    /** @var Promise<array<T>> */
    return new Promise(function (callable $resolve, callable $reject) use ($promisesOrValues, $cancellationQueue): void {
        $toResolve = 0;
        /** @var bool */
        $continue = \true;
        $values = [];
        foreach ($promisesOrValues as $i => $promiseOrValue) {
            $cancellationQueue->enqueue($promiseOrValue);
            $values[$i] = null;
            ++$toResolve;
            resolve($promiseOrValue)->then(function ($value) use ($i, &$values, &$toResolve, &$continue, $resolve): void {
                $values[$i] = $value;
                if (0 === --$toResolve && !$continue) {
                    $resolve($values);
                }
            }, function (\Throwable $reason) use (&$continue, $reject): void {
                $continue = \false;
                $reject($reason);
            });
            if (!$continue && !\is_array($promisesOrValues)) {
                break;
            }
        }
        $continue = \false;
        if ($toResolve === 0) {
            $resolve($values);
        }
    }, $cancellationQueue);
}
/**
 * Initiates a competitive race that allows one winner. Returns a promise which is
 * resolved in the same way the first settled promise resolves.
 *
 * The returned promise will become **infinitely pending** if  `$promisesOrValues`
 * contains 0 items.
 *
 * @template T
 * @param iterable<PromiseInterface<T>|T> $promisesOrValues
 * @return PromiseInterface<T>
 */
function race(iterable $promisesOrValues): PromiseInterface
{
    $cancellationQueue = new Internal\CancellationQueue();
    /** @var Promise<T> */
    return new Promise(function (callable $resolve, callable $reject) use ($promisesOrValues, $cancellationQueue): void {
        $continue = \true;
        foreach ($promisesOrValues as $promiseOrValue) {
            $cancellationQueue->enqueue($promiseOrValue);
            resolve($promiseOrValue)->then($resolve, $reject)->finally(function () use (&$continue): void {
                $continue = \false;
            });
            if (!$continue && !\is_array($promisesOrValues)) {
                break;
            }
        }
    }, $cancellationQueue);
}
/**
 * Returns a promise that will resolve when any one of the items in
 * `$promisesOrValues` resolves. The resolution value of the returned promise
 * will be the resolution value of the triggering item.
 *
 * The returned promise will only reject if *all* items in `$promisesOrValues` are
 * rejected. The rejection value will be an array of all rejection reasons.
 *
 * The returned promise will also reject with a `React\Promise\Exception\LengthException`
 * if `$promisesOrValues` contains 0 items.
 *
 * @template T
 * @param iterable<PromiseInterface<T>|T> $promisesOrValues
 * @return PromiseInterface<T>
 */
function any(iterable $promisesOrValues): PromiseInterface
{
    $cancellationQueue = new Internal\CancellationQueue();
    /** @var Promise<T> */
    return new Promise(function (callable $resolve, callable $reject) use ($promisesOrValues, $cancellationQueue): void {
        $toReject = 0;
        $continue = \true;
        $reasons = [];
        foreach ($promisesOrValues as $i => $promiseOrValue) {
            $cancellationQueue->enqueue($promiseOrValue);
            ++$toReject;
            resolve($promiseOrValue)->then(function ($value) use ($resolve, &$continue): void {
                $continue = \false;
                $resolve($value);
            }, function (\Throwable $reason) use ($i, &$reasons, &$toReject, $reject, &$continue): void {
                $reasons[$i] = $reason;
                if (0 === --$toReject && !$continue) {
                    $reject(new CompositeException($reasons, 'All promises rejected.'));
                }
            });
            if (!$continue && !\is_array($promisesOrValues)) {
                break;
            }
        }
        $continue = \false;
        if ($toReject === 0 && !$reasons) {
            $reject(new Exception\LengthException('Must contain at least 1 item but contains only 0 items.'));
        } elseif ($toReject === 0) {
            $reject(new CompositeException($reasons, 'All promises rejected.'));
        }
    }, $cancellationQueue);
}
/**
 * Sets the global rejection handler for unhandled promise rejections.
 *
 * Note that rejected promises should always be handled similar to how any
 * exceptions should always be caught in a `try` + `catch` block. If you remove
 * the last reference to a rejected promise that has not been handled, it will
 * report an unhandled promise rejection. See also the [`reject()` function](#reject)
 * for more details.
 *
 * The `?callable $callback` argument MUST be a valid callback function that
 * accepts a single `Throwable` argument or a `null` value to restore the
 * default promise rejection handler. The return value of the callback function
 * will be ignored and has no effect, so you SHOULD return a `void` value. The
 * callback function MUST NOT throw or the program will be terminated with a
 * fatal error.
 *
 * The function returns the previous rejection handler or `null` if using the
 * default promise rejection handler.
 *
 * The default promise rejection handler will log an error message plus its
 * stack trace:
 *
 * ```php
 * // Unhandled promise rejection with RuntimeException: Unhandled in example.php:2
 * React\Promise\reject(new RuntimeException('Unhandled'));
 * ```
 *
 * The promise rejection handler may be used to use customize the log message or
 * write to custom log targets. As a rule of thumb, this function should only be
 * used as a last resort and promise rejections are best handled with either the
 * [`then()` method](#promiseinterfacethen), the
 * [`catch()` method](#promiseinterfacecatch), or the
 * [`finally()` method](#promiseinterfacefinally).
 * See also the [`reject()` function](#reject) for more details.
 *
 * @param callable(\Throwable):void|null $callback
 * @return callable(\Throwable):void|null
 */
function set_rejection_handler(?callable $callback): ?callable
{
    static $current = null;
    $previous = $current;
    $current = $callback;
    return $previous;
}
/**
 * @internal
 */
function _checkTypehint(callable $callback, \Throwable $reason): bool
{
    if (\is_array($callback)) {
        $callbackReflection = new \ReflectionMethod($callback[0], $callback[1]);
    } elseif (\is_object($callback) && !$callback instanceof \Closure) {
        $callbackReflection = new \ReflectionMethod($callback, '__invoke');
    } else {
        assert($callback instanceof \Closure || \is_string($callback));
        $callbackReflection = new \ReflectionFunction($callback);
    }
    $parameters = $callbackReflection->getParameters();
    if (!isset($parameters[0])) {
        return \true;
    }
    $expectedException = $parameters[0];
    // Extract the type of the argument and handle different possibilities
    $type = $expectedException->getType();
    $isTypeUnion = \true;
    $types = [];
    switch (\true) {
        case $type === null:
            break;
        case $type instanceof \ReflectionNamedType:
            $types = [$type];
            break;
        case $type instanceof \ReflectionIntersectionType:
            $isTypeUnion = \false;
        case $type instanceof \ReflectionUnionType:
            $types = $type->getTypes();
            break;
        default:
            throw new \LogicException('Unexpected return value of ReflectionParameter::getType');
    }
    // If there is no type restriction, it matches
    if (empty($types)) {
        return \true;
    }
    foreach ($types as $type) {
        if ($type instanceof \ReflectionIntersectionType) {
            foreach ($type->getTypes() as $typeToMatch) {
                assert($typeToMatch instanceof \ReflectionNamedType);
                $name = $typeToMatch->getName();
                if (!$matches = !$typeToMatch->isBuiltin() && $reason instanceof $name) {
                    break;
                }
            }
            assert(isset($matches));
        } else {
            assert($type instanceof \ReflectionNamedType);
            $name = $type->getName();
            $matches = !$type->isBuiltin() && $reason instanceof $name;
        }
        // If we look for a single match (union), we can return early on match
        // If we look for a full match (intersection), we can return early on mismatch
        if ($matches) {
            if ($isTypeUnion) {
                return \true;
            }
        } else if (!$isTypeUnion) {
            return \false;
        }
    }
    // If we look for a single match (union) and did not return early, we matched no type and are false
    // If we look for a full match (intersection) and did not return early, we matched all types and are true
    return $isTypeUnion ? \false : \true;
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj;

if (!\function_exists('NightwatchAgent_kden27khxA4QoEfj\React\Promise\resolve')) {
    require __DIR__ . '/functions.php';
}
The MIT License (MIT)

Copyright (c) 2012 Christian Lück, Cees-Jan Kiewiet, Jan Sorgalla, Chris Boden, Igor Wiedler

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Socket;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\DuplexResourceStream;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\Util;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\WritableResourceStream;
use NightwatchAgent_kden27khxA4QoEfj\React\Stream\WritableStreamInterface;
/**
 * The actual connection implementation for ConnectionInterface
 *
 * This class should only be used internally, see ConnectionInterface instead.
 *
 * @see ConnectionInterface
 * @internal
 */
class Connection extends EventEmitter implements ConnectionInterface
{
    /**
     * Internal flag whether this is a Unix domain socket (UDS) connection
     *
     * @internal
     */
    public $unix = \false;
    /**
     * Internal flag whether encryption has been enabled on this connection
     *
     * Mostly used by internal StreamEncryption so that connection returns
     * `tls://` scheme for encrypted connections instead of `tcp://`.
     *
     * @internal
     */
    public $encryptionEnabled = \false;
    /** @internal */
    public $stream;
    private $input;
    public function __construct($resource, LoopInterface $loop)
    {
        // PHP < 7.3.3 (and PHP < 7.2.15) suffers from a bug where feof() might
        // block with 100% CPU usage on fragmented TLS records.
        // We try to work around this by always consuming the complete receive
        // buffer at once to avoid stale data in TLS buffers. This is known to
        // work around high CPU usage for well-behaving peers, but this may
        // cause very large data chunks for high throughput scenarios. The buggy
        // behavior can still be triggered due to network I/O buffers or
        // malicious peers on affected versions, upgrading is highly recommended.
        // @link https://bugs.php.net/bug.php?id=77390
        $clearCompleteBuffer = \PHP_VERSION_ID < 70215 || \PHP_VERSION_ID >= 70300 && \PHP_VERSION_ID < 70303;
        // PHP < 7.1.4 (and PHP < 7.0.18) suffers from a bug when writing big
        // chunks of data over TLS streams at once.
        // We try to work around this by limiting the write chunk size to 8192
        // bytes for older PHP versions only.
        // This is only a work-around and has a noticable performance penalty on
        // affected versions. Please update your PHP version.
        // This applies to all streams because TLS may be enabled later on.
        // See https://github.com/reactphp/socket/issues/105
        $limitWriteChunks = \PHP_VERSION_ID < 70018 || \PHP_VERSION_ID >= 70100 && \PHP_VERSION_ID < 70104;
        $this->input = new DuplexResourceStream($resource, $loop, $clearCompleteBuffer ? -1 : null, new WritableResourceStream($resource, $loop, null, $limitWriteChunks ? 8192 : null));
        $this->stream = $resource;
        Util::forwardEvents($this->input, $this, array('data', 'end', 'error', 'close', 'pipe', 'drain'));
        $this->input->on('close', array($this, 'close'));
    }
    public function isReadable()
    {
        return $this->input->isReadable();
    }
    public function isWritable()
    {
        return $this->input->isWritable();
    }
    public function pause()
    {
        $this->input->pause();
    }
    public function resume()
    {
        $this->input->resume();
    }
    public function pipe(WritableStreamInterface $dest, array $options = array())
    {
        return $this->input->pipe($dest, $options);
    }
    public function write($data)
    {
        return $this->input->write($data);
    }
    public function end($data = null)
    {
        $this->input->end($data);
    }
    public function close()
    {
        $this->input->close();
        $this->handleClose();
        $this->removeAllListeners();
    }
    public function handleClose()
    {
        if (!\is_resource($this->stream)) {
            return;
        }
        // Try to cleanly shut down socket and ignore any errors in case other
        // side already closed. Underlying Stream implementation will take care
        // of closing stream resource, so we otherwise keep this open here.
        @\stream_socket_shutdown($this->stream, \STREAM_SHUT_RDWR);
    }
    public function getRemoteAddress()
    {
        if (!\is_resource($this->stream)) {
            return null;
        }
        return $this->parseAddress(\stream_socket_get_name($this->stream, \true));
    }
    public function getLocalAddress()
    {
        if (!\is_resource($this->stream)) {
            return null;
        }
        return $this->parseAddress(\stream_socket_get_name($this->stream, \false));
    }
    private function parseAddress($address)
    {
        if ($address === \false) {
            return null;
        }
        if ($this->unix) {
            // remove trailing colon from address for HHVM < 3.19: https://3v4l.org/5C1lo
            // note that technically ":" is a valid address, so keep this in place otherwise
            if (\substr($address, -1) === ':' && \defined('HHVM_VERSION_ID') && \HHVM_VERSION_ID < 31900) {
                $address = (string) \substr($address, 0, -1);
                // @codeCoverageIgnore
            }
            // work around unknown addresses should return null value: https://3v4l.org/5C1lo and https://bugs.php.net/bug.php?id=74556
            // PHP uses "\0" string and HHVM uses empty string (colon removed above)
            if ($address === '' || $address[0] === "\x00") {
                return null;
                // @codeCoverageIgnore
            }
            return 'unix://' . $address;
        }
        // check if this is an IPv6 address which includes multiple colons but no square brackets
        $pos = \strrpos($address, ':');
        if ($pos !== \false && \strpos($address, ':') < $pos && \substr($address, 0, 1) !== '[') {
            $address = '[' . \substr($address, 0, $pos) . ']:' . \substr($address, $pos + 1);
            // @codeCoverageIgnore
        }
        return ($this->encryptionEnabled ? 'tls' : 'tcp') . '://' . $address;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Socket;

use NightwatchAgent_kden27khxA4QoEfj\React\Stream\DuplexStreamInterface;
/**
 * Any incoming and outgoing connection is represented by this interface,
 * such as a normal TCP/IP connection.
 *
 * An incoming or outgoing connection is a duplex stream (both readable and
 * writable) that implements React's
 * [`DuplexStreamInterface`](https://github.com/reactphp/stream#duplexstreaminterface).
 * It contains additional properties for the local and remote address (client IP)
 * where this connection has been established to/from.
 *
 * Most commonly, instances implementing this `ConnectionInterface` are emitted
 * by all classes implementing the [`ServerInterface`](#serverinterface) and
 * used by all classes implementing the [`ConnectorInterface`](#connectorinterface).
 *
 * Because the `ConnectionInterface` implements the underlying
 * [`DuplexStreamInterface`](https://github.com/reactphp/stream#duplexstreaminterface)
 * you can use any of its events and methods as usual:
 *
 * ```php
 * $connection->on('data', function ($chunk) {
 *     echo $chunk;
 * });
 *
 * $connection->on('end', function () {
 *     echo 'ended';
 * });
 *
 * $connection->on('error', function (Exception $e) {
 *     echo 'error: ' . $e->getMessage();
 * });
 *
 * $connection->on('close', function () {
 *     echo 'closed';
 * });
 *
 * $connection->write($data);
 * $connection->end($data = null);
 * $connection->close();
 * // …
 * ```
 *
 * For more details, see the
 * [`DuplexStreamInterface`](https://github.com/reactphp/stream#duplexstreaminterface).
 *
 * @see DuplexStreamInterface
 * @see ServerInterface
 * @see ConnectorInterface
 */
interface ConnectionInterface extends DuplexStreamInterface
{
    /**
     * Returns the full remote address (URI) where this connection has been established with
     *
     * ```php
     * $address = $connection->getRemoteAddress();
     * echo 'Connection with ' . $address . PHP_EOL;
     * ```
     *
     * If the remote address can not be determined or is unknown at this time (such as
     * after the connection has been closed), it MAY return a `NULL` value instead.
     *
     * Otherwise, it will return the full address (URI) as a string value, such
     * as `tcp://127.0.0.1:8080`, `tcp://[::1]:80`, `tls://127.0.0.1:443`,
     * `unix://example.sock` or `unix:///path/to/example.sock`.
     * Note that individual URI components are application specific and depend
     * on the underlying transport protocol.
     *
     * If this is a TCP/IP based connection and you only want the remote IP, you may
     * use something like this:
     *
     * ```php
     * $address = $connection->getRemoteAddress();
     * $ip = trim(parse_url($address, PHP_URL_HOST), '[]');
     * echo 'Connection with ' . $ip . PHP_EOL;
     * ```
     *
     * @return ?string remote address (URI) or null if unknown
     */
    public function getRemoteAddress();
    /**
     * Returns the full local address (full URI with scheme, IP and port) where this connection has been established with
     *
     * ```php
     * $address = $connection->getLocalAddress();
     * echo 'Connection with ' . $address . PHP_EOL;
     * ```
     *
     * If the local address can not be determined or is unknown at this time (such as
     * after the connection has been closed), it MAY return a `NULL` value instead.
     *
     * Otherwise, it will return the full address (URI) as a string value, such
     * as `tcp://127.0.0.1:8080`, `tcp://[::1]:80`, `tls://127.0.0.1:443`,
     * `unix://example.sock` or `unix:///path/to/example.sock`.
     * Note that individual URI components are application specific and depend
     * on the underlying transport protocol.
     *
     * This method complements the [`getRemoteAddress()`](#getremoteaddress) method,
     * so they should not be confused.
     *
     * If your `TcpServer` instance is listening on multiple interfaces (e.g. using
     * the address `0.0.0.0`), you can use this method to find out which interface
     * actually accepted this connection (such as a public or local interface).
     *
     * If your system has multiple interfaces (e.g. a WAN and a LAN interface),
     * you can use this method to find out which interface was actually
     * used for this connection.
     *
     * @return ?string local address (URI) or null if unknown
     * @see self::getRemoteAddress()
     */
    public function getLocalAddress();
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Socket;

use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Config\Config as DnsConfig;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Resolver\Factory as DnsFactory;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Resolver\ResolverInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
/**
 * The `Connector` class is the main class in this package that implements the
 * `ConnectorInterface` and allows you to create streaming connections.
 *
 * You can use this connector to create any kind of streaming connections, such
 * as plaintext TCP/IP, secure TLS or local Unix connection streams.
 *
 * Under the hood, the `Connector` is implemented as a *higher-level facade*
 * for the lower-level connectors implemented in this package. This means it
 * also shares all of their features and implementation details.
 * If you want to typehint in your higher-level protocol implementation, you SHOULD
 * use the generic [`ConnectorInterface`](#connectorinterface) instead.
 *
 * @see ConnectorInterface for the base interface
 */
final class Connector implements ConnectorInterface
{
    private $connectors = array();
    /**
     * Instantiate new `Connector`
     *
     * ```php
     * $connector = new React\Socket\Connector();
     * ```
     *
     * This class takes two optional arguments for more advanced usage:
     *
     * ```php
     * // constructor signature as of v1.9.0
     * $connector = new React\Socket\Connector(array $context = [], ?LoopInterface $loop = null);
     *
     * // legacy constructor signature before v1.9.0
     * $connector = new React\Socket\Connector(?LoopInterface $loop = null, array $context = []);
     * ```
     *
     * This class takes an optional `LoopInterface|null $loop` parameter that can be used to
     * pass the event loop instance to use for this object. You can use a `null` value
     * here in order to use the [default loop](https://github.com/reactphp/event-loop#loop).
     * This value SHOULD NOT be given unless you're sure you want to explicitly use a
     * given event loop instance.
     *
     * @param array|LoopInterface|null $context
     * @param null|LoopInterface|array $loop
     * @throws \InvalidArgumentException for invalid arguments
     */
    public function __construct($context = array(), $loop = null)
    {
        // swap arguments for legacy constructor signature
        if (($context instanceof LoopInterface || $context === null) && (\func_num_args() <= 1 || \is_array($loop))) {
            $swap = $loop === null ? array() : $loop;
            $loop = $context;
            $context = $swap;
        }
        if (!\is_array($context) || $loop !== null && !$loop instanceof LoopInterface) {
            throw new \InvalidArgumentException('Expected "array $context" and "?LoopInterface $loop" arguments');
        }
        // apply default options if not explicitly given
        $context += array('tcp' => \true, 'tls' => \true, 'unix' => \true, 'dns' => \true, 'timeout' => \true, 'happy_eyeballs' => \true);
        if ($context['timeout'] === \true) {
            $context['timeout'] = (float) \ini_get("default_socket_timeout");
        }
        if ($context['tcp'] instanceof ConnectorInterface) {
            $tcp = $context['tcp'];
        } else {
            $tcp = new TcpConnector($loop, \is_array($context['tcp']) ? $context['tcp'] : array());
        }
        if ($context['dns'] !== \false) {
            if ($context['dns'] instanceof ResolverInterface) {
                $resolver = $context['dns'];
            } else {
                if ($context['dns'] !== \true) {
                    $config = $context['dns'];
                } else {
                    // try to load nameservers from system config or default to Google's public DNS
                    $config = DnsConfig::loadSystemConfigBlocking();
                    if (!$config->nameservers) {
                        $config->nameservers[] = '8.8.8.8';
                        // @codeCoverageIgnore
                    }
                }
                $factory = new DnsFactory();
                $resolver = $factory->createCached($config, $loop);
            }
            if ($context['happy_eyeballs'] === \true) {
                $tcp = new HappyEyeBallsConnector($loop, $tcp, $resolver);
            } else {
                $tcp = new DnsConnector($tcp, $resolver);
            }
        }
        if ($context['tcp'] !== \false) {
            $context['tcp'] = $tcp;
            if ($context['timeout'] !== \false) {
                $context['tcp'] = new TimeoutConnector($context['tcp'], $context['timeout'], $loop);
            }
            $this->connectors['tcp'] = $context['tcp'];
        }
        if ($context['tls'] !== \false) {
            if (!$context['tls'] instanceof ConnectorInterface) {
                $context['tls'] = new SecureConnector($tcp, $loop, \is_array($context['tls']) ? $context['tls'] : array());
            }
            if ($context['timeout'] !== \false) {
                $context['tls'] = new TimeoutConnector($context['tls'], $context['timeout'], $loop);
            }
            $this->connectors['tls'] = $context['tls'];
        }
        if ($context['unix'] !== \false) {
            if (!$context['unix'] instanceof ConnectorInterface) {
                $context['unix'] = new UnixConnector($loop);
            }
            $this->connectors['unix'] = $context['unix'];
        }
    }
    public function connect($uri)
    {
        $scheme = 'tcp';
        if (\strpos($uri, '://') !== \false) {
            $scheme = (string) \substr($uri, 0, \strpos($uri, '://'));
        }
        if (!isset($this->connectors[$scheme])) {
            return \NightwatchAgent_kden27khxA4QoEfj\React\Promise\reject(new \RuntimeException('No connector available for URI scheme "' . $scheme . '" (EINVAL)', \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22)));
        }
        return $this->connectors[$scheme]->connect($uri);
    }
    /**
     * [internal] Builds on URI from the given URI parts and ip address with original hostname as query
     *
     * @param array  $parts
     * @param string $host
     * @param string $ip
     * @return string
     * @internal
     */
    public static function uri(array $parts, $host, $ip)
    {
        $uri = '';
        // prepend original scheme if known
        if (isset($parts['scheme'])) {
            $uri .= $parts['scheme'] . '://';
        }
        if (\strpos($ip, ':') !== \false) {
            // enclose IPv6 addresses in square brackets before appending port
            $uri .= '[' . $ip . ']';
        } else {
            $uri .= $ip;
        }
        // append original port if known
        if (isset($parts['port'])) {
            $uri .= ':' . $parts['port'];
        }
        // append orignal path if known
        if (isset($parts['path'])) {
            $uri .= $parts['path'];
        }
        // append original query if known
        if (isset($parts['query'])) {
            $uri .= '?' . $parts['query'];
        }
        // append original hostname as query if resolved via DNS and if
        // destination URI does not contain "hostname" query param already
        $args = array();
        \parse_str(isset($parts['query']) ? $parts['query'] : '', $args);
        if ($host !== $ip && !isset($args['hostname'])) {
            $uri .= (isset($parts['query']) ? '&' : '?') . 'hostname=' . \rawurlencode($host);
        }
        // append original fragment if known
        if (isset($parts['fragment'])) {
            $uri .= '#' . $parts['fragment'];
        }
        return $uri;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Socket;

/**
 * The `ConnectorInterface` is responsible for providing an interface for
 * establishing streaming connections, such as a normal TCP/IP connection.
 *
 * This is the main interface defined in this package and it is used throughout
 * React's vast ecosystem.
 *
 * Most higher-level components (such as HTTP, database or other networking
 * service clients) accept an instance implementing this interface to create their
 * TCP/IP connection to the underlying networking service.
 * This is usually done via dependency injection, so it's fairly simple to actually
 * swap this implementation against any other implementation of this interface.
 *
 * The interface only offers a single `connect()` method.
 *
 * @see ConnectionInterface
 */
interface ConnectorInterface
{
    /**
     * Creates a streaming connection to the given remote address
     *
     * If returns a Promise which either fulfills with a stream implementing
     * `ConnectionInterface` on success or rejects with an `Exception` if the
     * connection is not successful.
     *
     * ```php
     * $connector->connect('google.com:443')->then(
     *     function (React\Socket\ConnectionInterface $connection) {
     *         // connection successfully established
     *     },
     *     function (Exception $error) {
     *         // failed to connect due to $error
     *     }
     * );
     * ```
     *
     * The returned Promise MUST be implemented in such a way that it can be
     * cancelled when it is still pending. Cancelling a pending promise MUST
     * reject its value with an Exception. It SHOULD clean up any underlying
     * resources and references as applicable.
     *
     * ```php
     * $promise = $connector->connect($uri);
     *
     * $promise->cancel();
     * ```
     *
     * @param string $uri
     * @return \React\Promise\PromiseInterface<ConnectionInterface>
     *     Resolves with a `ConnectionInterface` on success or rejects with an `Exception` on error.
     * @see ConnectionInterface
     */
    public function connect($uri);
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Socket;

use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Resolver\ResolverInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\PromiseInterface;
final class DnsConnector implements ConnectorInterface
{
    private $connector;
    private $resolver;
    public function __construct(ConnectorInterface $connector, ResolverInterface $resolver)
    {
        $this->connector = $connector;
        $this->resolver = $resolver;
    }
    public function connect($uri)
    {
        $original = $uri;
        if (\strpos($uri, '://') === \false) {
            $uri = 'tcp://' . $uri;
            $parts = \parse_url($uri);
            if (isset($parts['scheme'])) {
                unset($parts['scheme']);
            }
        } else {
            $parts = \parse_url($uri);
        }
        if (!$parts || !isset($parts['host'])) {
            return Promise\reject(new \InvalidArgumentException('Given URI "' . $original . '" is invalid (EINVAL)', \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22)));
        }
        $host = \trim($parts['host'], '[]');
        $connector = $this->connector;
        // skip DNS lookup / URI manipulation if this URI already contains an IP
        if (@\inet_pton($host) !== \false) {
            return $connector->connect($original);
        }
        $promise = $this->resolver->resolve($host);
        $resolved = null;
        return new Promise\Promise(function ($resolve, $reject) use (&$promise, &$resolved, $uri, $connector, $host, $parts) {
            // resolve/reject with result of DNS lookup
            $promise->then(function ($ip) use (&$promise, &$resolved, $uri, $connector, $host, $parts) {
                $resolved = $ip;
                return $promise = $connector->connect(Connector::uri($parts, $host, $ip))->then(null, function (\Exception $e) use ($uri) {
                    if ($e instanceof \RuntimeException) {
                        $message = \preg_replace('/^(Connection to [^ ]+)[&?]hostname=[^ &]+/', '$1', $e->getMessage());
                        $e = new \RuntimeException('Connection to ' . $uri . ' failed: ' . $message, $e->getCode(), $e);
                        // avoid garbage references by replacing all closures in call stack.
                        // what a lovely piece of code!
                        $r = new \ReflectionProperty('Exception', 'trace');
                        if (\PHP_VERSION_ID < 80100) {
                            $r->setAccessible(\true);
                        }
                        $trace = $r->getValue($e);
                        // Exception trace arguments are not available on some PHP 7.4 installs
                        // @codeCoverageIgnoreStart
                        foreach ($trace as $ti => $one) {
                            if (isset($one['args'])) {
                                foreach ($one['args'] as $ai => $arg) {
                                    if ($arg instanceof \Closure) {
                                        $trace[$ti]['args'][$ai] = 'Object(' . \get_class($arg) . ')';
                                    }
                                }
                            }
                        }
                        // @codeCoverageIgnoreEnd
                        $r->setValue($e, $trace);
                    }
                    throw $e;
                });
            }, function ($e) use ($uri, $reject) {
                $reject(new \RuntimeException('Connection to ' . $uri . ' failed during DNS lookup: ' . $e->getMessage(), 0, $e));
            })->then($resolve, $reject);
        }, function ($_, $reject) use (&$promise, &$resolved, $uri) {
            // cancellation should reject connection attempt
            // reject DNS resolution with custom reason, otherwise rely on connection cancellation below
            if ($resolved === null) {
                $reject(new \RuntimeException('Connection to ' . $uri . ' cancelled during DNS lookup (ECONNABORTED)', \defined('SOCKET_ECONNABORTED') ? \SOCKET_ECONNABORTED : 103));
            }
            // (try to) cancel pending DNS lookup / connection attempt
            if ($promise instanceof PromiseInterface && \method_exists($promise, 'cancel')) {
                // overwrite callback arguments for PHP7+ only, so they do not show
                // up in the Exception trace and do not cause a possible cyclic reference.
                $_ = $reject = null;
                $promise->cancel();
                $promise = null;
            }
        });
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Socket;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Loop;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
/**
 * [Internal] The `FdServer` class implements the `ServerInterface` and
 * is responsible for accepting connections from an existing file descriptor.
 *
 * ```php
 * $socket = new React\Socket\FdServer(3);
 * ```
 *
 * Whenever a client connects, it will emit a `connection` event with a connection
 * instance implementing `ConnectionInterface`:
 *
 * ```php
 * $socket->on('connection', function (ConnectionInterface $connection) {
 *     echo 'Plaintext connection from ' . $connection->getRemoteAddress() . PHP_EOL;
 *     $connection->write('hello there!' . PHP_EOL);
 *     …
 * });
 * ```
 *
 * See also the `ServerInterface` for more details.
 *
 * @see ServerInterface
 * @see ConnectionInterface
 * @internal
 */
final class FdServer extends EventEmitter implements ServerInterface
{
    private $master;
    private $loop;
    private $unix = \false;
    private $listening = \false;
    /**
     * Creates a socket server and starts listening on the given file descriptor
     *
     * This starts accepting new incoming connections on the given file descriptor.
     * See also the `connection event` documented in the `ServerInterface`
     * for more details.
     *
     * ```php
     * $socket = new React\Socket\FdServer(3);
     * ```
     *
     * If the given FD is invalid or out of range, it will throw an `InvalidArgumentException`:
     *
     * ```php
     * // throws InvalidArgumentException
     * $socket = new React\Socket\FdServer(-1);
     * ```
     *
     * If the given FD appears to be valid, but listening on it fails (such as
     * if the FD does not exist or does not refer to a socket server), it will
     * throw a `RuntimeException`:
     *
     * ```php
     * // throws RuntimeException because FD does not reference a socket server
     * $socket = new React\Socket\FdServer(0, $loop);
     * ```
     *
     * Note that these error conditions may vary depending on your system and/or
     * configuration.
     * See the exception message and code for more details about the actual error
     * condition.
     *
     * @param int|string     $fd   FD number such as `3` or as URL in the form of `php://fd/3`
     * @param ?LoopInterface $loop
     * @throws \InvalidArgumentException if the listening address is invalid
     * @throws \RuntimeException if listening on this address fails (already in use etc.)
     */
    public function __construct($fd, $loop = null)
    {
        if (\preg_match('#^php://fd/(\d+)$#', $fd, $m)) {
            $fd = (int) $m[1];
        }
        if (!\is_int($fd) || $fd < 0 || $fd >= \PHP_INT_MAX) {
            throw new \InvalidArgumentException('Invalid FD number given (EINVAL)', \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22));
        }
        if ($loop !== null && !$loop instanceof LoopInterface) {
            // manual type check to support legacy PHP < 7.1
            throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
        }
        $this->loop = $loop ?: Loop::get();
        $errno = 0;
        $errstr = '';
        \set_error_handler(function ($_, $error) use (&$errno, &$errstr) {
            // Match errstr from PHP's warning message.
            // fopen(php://fd/3): Failed to open stream: Error duping file descriptor 3; possibly it doesn't exist: [9]: Bad file descriptor
            \preg_match('/\[(\d+)\]: (.*)/', $error, $m);
            $errno = isset($m[1]) ? (int) $m[1] : 0;
            $errstr = isset($m[2]) ? $m[2] : $error;
        });
        $this->master = \fopen('php://fd/' . $fd, 'r+');
        \restore_error_handler();
        if (\false === $this->master) {
            throw new \RuntimeException('Failed to listen on FD ' . $fd . ': ' . $errstr . SocketServer::errconst($errno), $errno);
        }
        $meta = \stream_get_meta_data($this->master);
        if (!isset($meta['stream_type']) || $meta['stream_type'] !== 'tcp_socket') {
            \fclose($this->master);
            $errno = \defined('SOCKET_ENOTSOCK') ? \SOCKET_ENOTSOCK : 88;
            $errstr = \function_exists('socket_strerror') ? \socket_strerror($errno) : 'Not a socket';
            throw new \RuntimeException('Failed to listen on FD ' . $fd . ': ' . $errstr . ' (ENOTSOCK)', $errno);
        }
        // Socket should not have a peer address if this is a listening socket.
        // Looks like this work-around is the closest we can get because PHP doesn't expose SO_ACCEPTCONN even with ext-sockets.
        if (\stream_socket_get_name($this->master, \true) !== \false) {
            \fclose($this->master);
            $errno = \defined('SOCKET_EISCONN') ? \SOCKET_EISCONN : 106;
            $errstr = \function_exists('socket_strerror') ? \socket_strerror($errno) : 'Socket is connected';
            throw new \RuntimeException('Failed to listen on FD ' . $fd . ': ' . $errstr . ' (EISCONN)', $errno);
        }
        // Assume this is a Unix domain socket (UDS) when its listening address doesn't parse as a valid URL with a port.
        // Looks like this work-around is the closest we can get because PHP doesn't expose SO_DOMAIN even with ext-sockets.
        $this->unix = \parse_url($this->getAddress(), \PHP_URL_PORT) === \false;
        \stream_set_blocking($this->master, \false);
        $this->resume();
    }
    public function getAddress()
    {
        if (!\is_resource($this->master)) {
            return null;
        }
        $address = \stream_socket_get_name($this->master, \false);
        if ($this->unix === \true) {
            return 'unix://' . $address;
        }
        // check if this is an IPv6 address which includes multiple colons but no square brackets
        $pos = \strrpos($address, ':');
        if ($pos !== \false && \strpos($address, ':') < $pos && \substr($address, 0, 1) !== '[') {
            $address = '[' . \substr($address, 0, $pos) . ']:' . \substr($address, $pos + 1);
            // @codeCoverageIgnore
        }
        return 'tcp://' . $address;
    }
    public function pause()
    {
        if (!$this->listening) {
            return;
        }
        $this->loop->removeReadStream($this->master);
        $this->listening = \false;
    }
    public function resume()
    {
        if ($this->listening || !\is_resource($this->master)) {
            return;
        }
        $that = $this;
        $this->loop->addReadStream($this->master, function ($master) use ($that) {
            try {
                $newSocket = SocketServer::accept($master);
            } catch (\RuntimeException $e) {
                $that->emit('error', array($e));
                return;
            }
            $that->handleConnection($newSocket);
        });
        $this->listening = \true;
    }
    public function close()
    {
        if (!\is_resource($this->master)) {
            return;
        }
        $this->pause();
        \fclose($this->master);
        $this->removeAllListeners();
    }
    /** @internal */
    public function handleConnection($socket)
    {
        $connection = new Connection($socket, $this->loop);
        $connection->unix = $this->unix;
        $this->emit('connection', array($connection));
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Socket;

/**
 * Decorates an existing Connector to always use a fixed, preconfigured URI
 *
 * This can be useful for consumers that do not support certain URIs, such as
 * when you want to explicitly connect to a Unix domain socket (UDS) path
 * instead of connecting to a default address assumed by an higher-level API:
 *
 * ```php
 * $connector = new React\Socket\FixedUriConnector(
 *     'unix:///var/run/docker.sock',
 *     new React\Socket\UnixConnector()
 * );
 *
 * // destination will be ignored, actually connects to Unix domain socket
 * $promise = $connector->connect('localhost:80');
 * ```
 */
class FixedUriConnector implements ConnectorInterface
{
    private $uri;
    private $connector;
    /**
     * @param string $uri
     * @param ConnectorInterface $connector
     */
    public function __construct($uri, ConnectorInterface $connector)
    {
        $this->uri = $uri;
        $this->connector = $connector;
    }
    public function connect($_)
    {
        return $this->connector->connect($this->uri);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Socket;

use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Model\Message;
use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Resolver\ResolverInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\TimerInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\PromiseInterface;
/**
 * @internal
 */
final class HappyEyeBallsConnectionBuilder
{
    /**
     * As long as we haven't connected yet keep popping an IP address of the connect queue until one of them
     * succeeds or they all fail. We will wait 100ms between connection attempts as per RFC.
     *
     * @link https://tools.ietf.org/html/rfc8305#section-5
     */
    const CONNECTION_ATTEMPT_DELAY = 0.1;
    /**
     * Delay `A` lookup by 50ms sending out connection to IPv4 addresses when IPv6 records haven't
     * resolved yet as per RFC.
     *
     * @link https://tools.ietf.org/html/rfc8305#section-3
     */
    const RESOLUTION_DELAY = 0.05;
    public $loop;
    public $connector;
    public $resolver;
    public $uri;
    public $host;
    public $resolved = array(Message::TYPE_A => \false, Message::TYPE_AAAA => \false);
    public $resolverPromises = array();
    public $connectionPromises = array();
    public $connectQueue = array();
    public $nextAttemptTimer;
    public $parts;
    public $ipsCount = 0;
    public $failureCount = 0;
    public $resolve;
    public $reject;
    public $lastErrorFamily;
    public $lastError6;
    public $lastError4;
    public function __construct(LoopInterface $loop, ConnectorInterface $connector, ResolverInterface $resolver, $uri, $host, $parts)
    {
        $this->loop = $loop;
        $this->connector = $connector;
        $this->resolver = $resolver;
        $this->uri = $uri;
        $this->host = $host;
        $this->parts = $parts;
    }
    public function connect()
    {
        $that = $this;
        return new Promise\Promise(function ($resolve, $reject) use ($that) {
            $lookupResolve = function ($type) use ($that, $resolve, $reject) {
                return function (array $ips) use ($that, $type, $resolve, $reject) {
                    unset($that->resolverPromises[$type]);
                    $that->resolved[$type] = \true;
                    $that->mixIpsIntoConnectQueue($ips);
                    // start next connection attempt if not already awaiting next
                    if ($that->nextAttemptTimer === null && $that->connectQueue) {
                        $that->check($resolve, $reject);
                    }
                };
            };
            $that->resolverPromises[Message::TYPE_AAAA] = $that->resolve(Message::TYPE_AAAA, $reject)->then($lookupResolve(Message::TYPE_AAAA));
            $that->resolverPromises[Message::TYPE_A] = $that->resolve(Message::TYPE_A, $reject)->then(function (array $ips) use ($that) {
                // happy path: IPv6 has resolved already (or could not resolve), continue with IPv4 addresses
                if ($that->resolved[Message::TYPE_AAAA] === \true || !$ips) {
                    return $ips;
                }
                // Otherwise delay processing IPv4 lookup until short timer passes or IPv6 resolves in the meantime
                $deferred = new Promise\Deferred(function () use (&$ips) {
                    // discard all IPv4 addresses if cancelled
                    $ips = array();
                });
                $timer = $that->loop->addTimer($that::RESOLUTION_DELAY, function () use ($deferred, $ips) {
                    $deferred->resolve($ips);
                });
                $that->resolverPromises[Message::TYPE_AAAA]->then(function () use ($that, $timer, $deferred, &$ips) {
                    $that->loop->cancelTimer($timer);
                    $deferred->resolve($ips);
                });
                return $deferred->promise();
            })->then($lookupResolve(Message::TYPE_A));
        }, function ($_, $reject) use ($that) {
            $reject(new \RuntimeException('Connection to ' . $that->uri . ' cancelled' . (!$that->connectionPromises ? ' during DNS lookup' : '') . ' (ECONNABORTED)', \defined('SOCKET_ECONNABORTED') ? \SOCKET_ECONNABORTED : 103));
            $_ = $reject = null;
            $that->cleanUp();
        });
    }
    /**
     * @internal
     * @param int      $type   DNS query type
     * @param callable $reject
     * @return \React\Promise\PromiseInterface<string[]> Returns a promise that
     *     always resolves with a list of IP addresses on success or an empty
     *     list on error.
     */
    public function resolve($type, $reject)
    {
        $that = $this;
        return $that->resolver->resolveAll($that->host, $type)->then(null, function (\Exception $e) use ($type, $reject, $that) {
            unset($that->resolverPromises[$type]);
            $that->resolved[$type] = \true;
            if ($type === Message::TYPE_A) {
                $that->lastError4 = $e->getMessage();
                $that->lastErrorFamily = 4;
            } else {
                $that->lastError6 = $e->getMessage();
                $that->lastErrorFamily = 6;
            }
            // cancel next attempt timer when there are no more IPs to connect to anymore
            if ($that->nextAttemptTimer !== null && !$that->connectQueue) {
                $that->loop->cancelTimer($that->nextAttemptTimer);
                $that->nextAttemptTimer = null;
            }
            if ($that->hasBeenResolved() && $that->ipsCount === 0) {
                $reject(new \RuntimeException($that->error(), 0, $e));
            }
            // Exception already handled above, so don't throw an unhandled rejection here
            return array();
        });
    }
    /**
     * @internal
     */
    public function check($resolve, $reject)
    {
        $ip = \array_shift($this->connectQueue);
        // start connection attempt and remember array position to later unset again
        $this->connectionPromises[] = $this->attemptConnection($ip);
        \end($this->connectionPromises);
        $index = \key($this->connectionPromises);
        $that = $this;
        $that->connectionPromises[$index]->then(function ($connection) use ($that, $index, $resolve) {
            unset($that->connectionPromises[$index]);
            $that->cleanUp();
            $resolve($connection);
        }, function (\Exception $e) use ($that, $index, $ip, $resolve, $reject) {
            unset($that->connectionPromises[$index]);
            $that->failureCount++;
            $message = \preg_replace('/^(Connection to [^ ]+)[&?]hostname=[^ &]+/', '$1', $e->getMessage());
            if (\strpos($ip, ':') === \false) {
                $that->lastError4 = $message;
                $that->lastErrorFamily = 4;
            } else {
                $that->lastError6 = $message;
                $that->lastErrorFamily = 6;
            }
            // start next connection attempt immediately on error
            if ($that->connectQueue) {
                if ($that->nextAttemptTimer !== null) {
                    $that->loop->cancelTimer($that->nextAttemptTimer);
                    $that->nextAttemptTimer = null;
                }
                $that->check($resolve, $reject);
            }
            if ($that->hasBeenResolved() === \false) {
                return;
            }
            if ($that->ipsCount === $that->failureCount) {
                $that->cleanUp();
                $reject(new \RuntimeException($that->error(), $e->getCode(), $e));
            }
        });
        // Allow next connection attempt in 100ms: https://tools.ietf.org/html/rfc8305#section-5
        // Only start timer when more IPs are queued or when DNS query is still pending (might add more IPs)
        if ($this->nextAttemptTimer === null && (\count($this->connectQueue) > 0 || $this->resolved[Message::TYPE_A] === \false || $this->resolved[Message::TYPE_AAAA] === \false)) {
            $this->nextAttemptTimer = $this->loop->addTimer(self::CONNECTION_ATTEMPT_DELAY, function () use ($that, $resolve, $reject) {
                $that->nextAttemptTimer = null;
                if ($that->connectQueue) {
                    $that->check($resolve, $reject);
                }
            });
        }
    }
    /**
     * @internal
     */
    public function attemptConnection($ip)
    {
        $uri = Connector::uri($this->parts, $this->host, $ip);
        return $this->connector->connect($uri);
    }
    /**
     * @internal
     */
    public function cleanUp()
    {
        // clear list of outstanding IPs to avoid creating new connections
        $this->connectQueue = array();
        // cancel pending connection attempts
        foreach ($this->connectionPromises as $connectionPromise) {
            if ($connectionPromise instanceof PromiseInterface && \method_exists($connectionPromise, 'cancel')) {
                $connectionPromise->cancel();
            }
        }
        // cancel pending DNS resolution (cancel IPv4 first in case it is awaiting IPv6 resolution delay)
        foreach (\array_reverse($this->resolverPromises) as $resolverPromise) {
            if ($resolverPromise instanceof PromiseInterface && \method_exists($resolverPromise, 'cancel')) {
                $resolverPromise->cancel();
            }
        }
        if ($this->nextAttemptTimer instanceof TimerInterface) {
            $this->loop->cancelTimer($this->nextAttemptTimer);
            $this->nextAttemptTimer = null;
        }
    }
    /**
     * @internal
     */
    public function hasBeenResolved()
    {
        foreach ($this->resolved as $typeHasBeenResolved) {
            if ($typeHasBeenResolved === \false) {
                return \false;
            }
        }
        return \true;
    }
    /**
     * Mixes an array of IP addresses into the connect queue in such a way they alternate when attempting to connect.
     * The goal behind it is first attempt to connect to IPv6, then to IPv4, then to IPv6 again until one of those
     * attempts succeeds.
     *
     * @link https://tools.ietf.org/html/rfc8305#section-4
     *
     * @internal
     */
    public function mixIpsIntoConnectQueue(array $ips)
    {
        \shuffle($ips);
        $this->ipsCount += \count($ips);
        $connectQueueStash = $this->connectQueue;
        $this->connectQueue = array();
        while (\count($connectQueueStash) > 0 || \count($ips) > 0) {
            if (\count($ips) > 0) {
                $this->connectQueue[] = \array_shift($ips);
            }
            if (\count($connectQueueStash) > 0) {
                $this->connectQueue[] = \array_shift($connectQueueStash);
            }
        }
    }
    /**
     * @internal
     * @return string
     */
    public function error()
    {
        if ($this->lastError4 === $this->lastError6) {
            $message = $this->lastError6;
        } elseif ($this->lastErrorFamily === 6) {
            $message = 'Last error for IPv6: ' . $this->lastError6 . '. Previous error for IPv4: ' . $this->lastError4;
        } else {
            $message = 'Last error for IPv4: ' . $this->lastError4 . '. Previous error for IPv6: ' . $this->lastError6;
        }
        if ($this->hasBeenResolved() && $this->ipsCount === 0) {
            if ($this->lastError6 === $this->lastError4) {
                $message = ' during DNS lookup: ' . $this->lastError6;
            } else {
                $message = ' during DNS lookup. ' . $message;
            }
        } else {
            $message = ': ' . $message;
        }
        return 'Connection to ' . $this->uri . ' failed' . $message;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Socket;

use NightwatchAgent_kden27khxA4QoEfj\React\Dns\Resolver\ResolverInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Loop;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise;
final class HappyEyeBallsConnector implements ConnectorInterface
{
    private $loop;
    private $connector;
    private $resolver;
    /**
     * @param ?LoopInterface $loop
     * @param ConnectorInterface $connector
     * @param ResolverInterface $resolver
     */
    public function __construct($loop = null, $connector = null, $resolver = null)
    {
        // $connector and $resolver arguments are actually required, marked
        // optional for technical reasons only. Nullable $loop without default
        // requires PHP 7.1, null default is also supported in legacy PHP
        // versions, but required parameters are not allowed after arguments
        // with null default. Mark all parameters optional and check accordingly.
        if ($loop !== null && !$loop instanceof LoopInterface) {
            // manual type check to support legacy PHP < 7.1
            throw new \InvalidArgumentException('Argument #1 ($loop) expected null|React\EventLoop\LoopInterface');
        }
        if (!$connector instanceof ConnectorInterface) {
            // manual type check to support legacy PHP < 7.1
            throw new \InvalidArgumentException('Argument #2 ($connector) expected React\Socket\ConnectorInterface');
        }
        if (!$resolver instanceof ResolverInterface) {
            // manual type check to support legacy PHP < 7.1
            throw new \InvalidArgumentException('Argument #3 ($resolver) expected React\Dns\Resolver\ResolverInterface');
        }
        $this->loop = $loop ?: Loop::get();
        $this->connector = $connector;
        $this->resolver = $resolver;
    }
    public function connect($uri)
    {
        $original = $uri;
        if (\strpos($uri, '://') === \false) {
            $uri = 'tcp://' . $uri;
            $parts = \parse_url($uri);
            if (isset($parts['scheme'])) {
                unset($parts['scheme']);
            }
        } else {
            $parts = \parse_url($uri);
        }
        if (!$parts || !isset($parts['host'])) {
            return Promise\reject(new \InvalidArgumentException('Given URI "' . $original . '" is invalid (EINVAL)', \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22)));
        }
        $host = \trim($parts['host'], '[]');
        // skip DNS lookup / URI manipulation if this URI already contains an IP
        if (@\inet_pton($host) !== \false) {
            return $this->connector->connect($original);
        }
        $builder = new HappyEyeBallsConnectionBuilder($this->loop, $this->connector, $this->resolver, $uri, $host, $parts);
        return $builder->connect();
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Socket;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use Exception;
use OverflowException;
/**
 * The `LimitingServer` decorator wraps a given `ServerInterface` and is responsible
 * for limiting and keeping track of open connections to this server instance.
 *
 * Whenever the underlying server emits a `connection` event, it will check its
 * limits and then either
 * - keep track of this connection by adding it to the list of
 *   open connections and then forward the `connection` event
 * - or reject (close) the connection when its limits are exceeded and will
 *   forward an `error` event instead.
 *
 * Whenever a connection closes, it will remove this connection from the list of
 * open connections.
 *
 * ```php
 * $server = new React\Socket\LimitingServer($server, 100);
 * $server->on('connection', function (React\Socket\ConnectionInterface $connection) {
 *     $connection->write('hello there!' . PHP_EOL);
 *     …
 * });
 * ```
 *
 * See also the `ServerInterface` for more details.
 *
 * @see ServerInterface
 * @see ConnectionInterface
 */
class LimitingServer extends EventEmitter implements ServerInterface
{
    private $connections = array();
    private $server;
    private $limit;
    private $pauseOnLimit = \false;
    private $autoPaused = \false;
    private $manuPaused = \false;
    /**
     * Instantiates a new LimitingServer.
     *
     * You have to pass a maximum number of open connections to ensure
     * the server will automatically reject (close) connections once this limit
     * is exceeded. In this case, it will emit an `error` event to inform about
     * this and no `connection` event will be emitted.
     *
     * ```php
     * $server = new React\Socket\LimitingServer($server, 100);
     * $server->on('connection', function (React\Socket\ConnectionInterface $connection) {
     *     $connection->write('hello there!' . PHP_EOL);
     *     …
     * });
     * ```
     *
     * You MAY pass a `null` limit in order to put no limit on the number of
     * open connections and keep accepting new connection until you run out of
     * operating system resources (such as open file handles). This may be
     * useful if you do not want to take care of applying a limit but still want
     * to use the `getConnections()` method.
     *
     * You can optionally configure the server to pause accepting new
     * connections once the connection limit is reached. In this case, it will
     * pause the underlying server and no longer process any new connections at
     * all, thus also no longer closing any excessive connections.
     * The underlying operating system is responsible for keeping a backlog of
     * pending connections until its limit is reached, at which point it will
     * start rejecting further connections.
     * Once the server is below the connection limit, it will continue consuming
     * connections from the backlog and will process any outstanding data on
     * each connection.
     * This mode may be useful for some protocols that are designed to wait for
     * a response message (such as HTTP), but may be less useful for other
     * protocols that demand immediate responses (such as a "welcome" message in
     * an interactive chat).
     *
     * ```php
     * $server = new React\Socket\LimitingServer($server, 100, true);
     * $server->on('connection', function (React\Socket\ConnectionInterface $connection) {
     *     $connection->write('hello there!' . PHP_EOL);
     *     …
     * });
     * ```
     *
     * @param ServerInterface $server
     * @param int|null        $connectionLimit
     * @param bool            $pauseOnLimit
     */
    public function __construct(ServerInterface $server, $connectionLimit, $pauseOnLimit = \false)
    {
        $this->server = $server;
        $this->limit = $connectionLimit;
        if ($connectionLimit !== null) {
            $this->pauseOnLimit = $pauseOnLimit;
        }
        $this->server->on('connection', array($this, 'handleConnection'));
        $this->server->on('error', array($this, 'handleError'));
    }
    /**
     * Returns an array with all currently active connections
     *
     * ```php
     * foreach ($server->getConnection() as $connection) {
     *     $connection->write('Hi!');
     * }
     * ```
     *
     * @return ConnectionInterface[]
     */
    public function getConnections()
    {
        return $this->connections;
    }
    public function getAddress()
    {
        return $this->server->getAddress();
    }
    public function pause()
    {
        if (!$this->manuPaused) {
            $this->manuPaused = \true;
            if (!$this->autoPaused) {
                $this->server->pause();
            }
        }
    }
    public function resume()
    {
        if ($this->manuPaused) {
            $this->manuPaused = \false;
            if (!$this->autoPaused) {
                $this->server->resume();
            }
        }
    }
    public function close()
    {
        $this->server->close();
    }
    /** @internal */
    public function handleConnection(ConnectionInterface $connection)
    {
        // close connection if limit exceeded
        if ($this->limit !== null && \count($this->connections) >= $this->limit) {
            $this->handleError(new \OverflowException('Connection closed because server reached connection limit'));
            $connection->close();
            return;
        }
        $this->connections[] = $connection;
        $that = $this;
        $connection->on('close', function () use ($that, $connection) {
            $that->handleDisconnection($connection);
        });
        // pause accepting new connections if limit exceeded
        if ($this->pauseOnLimit && !$this->autoPaused && \count($this->connections) >= $this->limit) {
            $this->autoPaused = \true;
            if (!$this->manuPaused) {
                $this->server->pause();
            }
        }
        $this->emit('connection', array($connection));
    }
    /** @internal */
    public function handleDisconnection(ConnectionInterface $connection)
    {
        unset($this->connections[\array_search($connection, $this->connections)]);
        // continue accepting new connection if below limit
        if ($this->autoPaused && \count($this->connections) < $this->limit) {
            $this->autoPaused = \false;
            if (!$this->manuPaused) {
                $this->server->resume();
            }
        }
    }
    /** @internal */
    public function handleError(\Exception $error)
    {
        $this->emit('error', array($error));
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Socket;

use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Loop;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise;
use BadMethodCallException;
use InvalidArgumentException;
use UnexpectedValueException;
final class SecureConnector implements ConnectorInterface
{
    private $connector;
    private $streamEncryption;
    private $context;
    /**
     * @param ConnectorInterface $connector
     * @param ?LoopInterface $loop
     * @param array $context
     */
    public function __construct(ConnectorInterface $connector, $loop = null, array $context = array())
    {
        if ($loop !== null && !$loop instanceof LoopInterface) {
            // manual type check to support legacy PHP < 7.1
            throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
        }
        $this->connector = $connector;
        $this->streamEncryption = new StreamEncryption($loop ?: Loop::get(), \false);
        $this->context = $context;
    }
    public function connect($uri)
    {
        if (!\function_exists('stream_socket_enable_crypto') && !\function_exists('NightwatchAgent_kden27khxA4QoEfj\stream_socket_enable_crypto')) {
            return Promise\reject(new \BadMethodCallException('Encryption not supported on your platform (HHVM < 3.8?)'));
            // @codeCoverageIgnore
        }
        if (\strpos($uri, '://') === \false) {
            $uri = 'tls://' . $uri;
        }
        $parts = \parse_url($uri);
        if (!$parts || !isset($parts['scheme']) || $parts['scheme'] !== 'tls') {
            return Promise\reject(new \InvalidArgumentException('Given URI "' . $uri . '" is invalid (EINVAL)', \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22)));
        }
        $context = $this->context;
        $encryption = $this->streamEncryption;
        $connected = \false;
        /** @var \React\Promise\PromiseInterface<ConnectionInterface> $promise */
        $promise = $this->connector->connect(\str_replace('tls://', '', $uri))->then(function (ConnectionInterface $connection) use ($context, $encryption, $uri, &$promise, &$connected) {
            // (unencrypted) TCP/IP connection succeeded
            $connected = \true;
            if (!$connection instanceof Connection) {
                $connection->close();
                throw new \UnexpectedValueException('Base connector does not use internal Connection class exposing stream resource');
            }
            // set required SSL/TLS context options
            foreach ($context as $name => $value) {
                \stream_context_set_option($connection->stream, 'ssl', $name, $value);
            }
            // try to enable encryption
            return $promise = $encryption->enable($connection)->then(null, function ($error) use ($connection, $uri) {
                // establishing encryption failed => close invalid connection and return error
                $connection->close();
                throw new \RuntimeException('Connection to ' . $uri . ' failed during TLS handshake: ' . $error->getMessage(), $error->getCode());
            });
        }, function (\Exception $e) use ($uri) {
            if ($e instanceof \RuntimeException) {
                $message = \preg_replace('/^Connection to [^ ]+/', '', $e->getMessage());
                $e = new \RuntimeException('Connection to ' . $uri . $message, $e->getCode(), $e);
                // avoid garbage references by replacing all closures in call stack.
                // what a lovely piece of code!
                $r = new \ReflectionProperty('Exception', 'trace');
                if (\PHP_VERSION_ID < 80100) {
                    $r->setAccessible(\true);
                }
                $trace = $r->getValue($e);
                // Exception trace arguments are not available on some PHP 7.4 installs
                // @codeCoverageIgnoreStart
                foreach ($trace as $ti => $one) {
                    if (isset($one['args'])) {
                        foreach ($one['args'] as $ai => $arg) {
                            if ($arg instanceof \Closure) {
                                $trace[$ti]['args'][$ai] = 'Object(' . \get_class($arg) . ')';
                            }
                        }
                    }
                }
                // @codeCoverageIgnoreEnd
                $r->setValue($e, $trace);
            }
            throw $e;
        });
        return new \NightwatchAgent_kden27khxA4QoEfj\React\Promise\Promise(function ($resolve, $reject) use ($promise) {
            $promise->then($resolve, $reject);
        }, function ($_, $reject) use (&$promise, $uri, &$connected) {
            if ($connected) {
                $reject(new \RuntimeException('Connection to ' . $uri . ' cancelled during TLS handshake (ECONNABORTED)', \defined('SOCKET_ECONNABORTED') ? \SOCKET_ECONNABORTED : 103));
            }
            $promise->cancel();
            $promise = null;
        });
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Socket;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Loop;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use BadMethodCallException;
use UnexpectedValueException;
/**
 * The `SecureServer` class implements the `ServerInterface` and is responsible
 * for providing a secure TLS (formerly known as SSL) server.
 *
 * It does so by wrapping a `TcpServer` instance which waits for plaintext
 * TCP/IP connections and then performs a TLS handshake for each connection.
 *
 * ```php
 * $server = new React\Socket\TcpServer(8000);
 * $server = new React\Socket\SecureServer($server, null, array(
 *     // tls context options here…
 * ));
 * ```
 *
 * Whenever a client completes the TLS handshake, it will emit a `connection` event
 * with a connection instance implementing [`ConnectionInterface`](#connectioninterface):
 *
 * ```php
 * $server->on('connection', function (React\Socket\ConnectionInterface $connection) {
 *     echo 'Secure connection from' . $connection->getRemoteAddress() . PHP_EOL;
 *
 *     $connection->write('hello there!' . PHP_EOL);
 *     …
 * });
 * ```
 *
 * Whenever a client fails to perform a successful TLS handshake, it will emit an
 * `error` event and then close the underlying TCP/IP connection:
 *
 * ```php
 * $server->on('error', function (Exception $e) {
 *     echo 'Error' . $e->getMessage() . PHP_EOL;
 * });
 * ```
 *
 * See also the `ServerInterface` for more details.
 *
 * Note that the `SecureServer` class is a concrete implementation for TLS sockets.
 * If you want to typehint in your higher-level protocol implementation, you SHOULD
 * use the generic `ServerInterface` instead.
 *
 * @see ServerInterface
 * @see ConnectionInterface
 */
final class SecureServer extends EventEmitter implements ServerInterface
{
    private $tcp;
    private $encryption;
    private $context;
    /**
     * Creates a secure TLS server and starts waiting for incoming connections
     *
     * It does so by wrapping a `TcpServer` instance which waits for plaintext
     * TCP/IP connections and then performs a TLS handshake for each connection.
     * It thus requires valid [TLS context options],
     * which in its most basic form may look something like this if you're using a
     * PEM encoded certificate file:
     *
     * ```php
     * $server = new React\Socket\TcpServer(8000);
     * $server = new React\Socket\SecureServer($server, null, array(
     *     'local_cert' => 'server.pem'
     * ));
     * ```
     *
     * Note that the certificate file will not be loaded on instantiation but when an
     * incoming connection initializes its TLS context.
     * This implies that any invalid certificate file paths or contents will only cause
     * an `error` event at a later time.
     *
     * If your private key is encrypted with a passphrase, you have to specify it
     * like this:
     *
     * ```php
     * $server = new React\Socket\TcpServer(8000);
     * $server = new React\Socket\SecureServer($server, null, array(
     *     'local_cert' => 'server.pem',
     *     'passphrase' => 'secret'
     * ));
     * ```
     *
     * Note that available [TLS context options],
     * their defaults and effects of changing these may vary depending on your system
     * and/or PHP version.
     * Passing unknown context options has no effect.
     *
     * This class takes an optional `LoopInterface|null $loop` parameter that can be used to
     * pass the event loop instance to use for this object. You can use a `null` value
     * here in order to use the [default loop](https://github.com/reactphp/event-loop#loop).
     * This value SHOULD NOT be given unless you're sure you want to explicitly use a
     * given event loop instance.
     *
     * Advanced usage: Despite allowing any `ServerInterface` as first parameter,
     * you SHOULD pass a `TcpServer` instance as first parameter, unless you
     * know what you're doing.
     * Internally, the `SecureServer` has to set the required TLS context options on
     * the underlying stream resources.
     * These resources are not exposed through any of the interfaces defined in this
     * package, but only through the internal `Connection` class.
     * The `TcpServer` class is guaranteed to emit connections that implement
     * the `ConnectionInterface` and uses the internal `Connection` class in order to
     * expose these underlying resources.
     * If you use a custom `ServerInterface` and its `connection` event does not
     * meet this requirement, the `SecureServer` will emit an `error` event and
     * then close the underlying connection.
     *
     * @param ServerInterface|TcpServer $tcp
     * @param ?LoopInterface $loop
     * @param array $context
     * @throws BadMethodCallException for legacy HHVM < 3.8 due to lack of support
     * @see TcpServer
     * @link https://www.php.net/manual/en/context.ssl.php for TLS context options
     */
    public function __construct(ServerInterface $tcp, $loop = null, array $context = array())
    {
        if ($loop !== null && !$loop instanceof LoopInterface) {
            // manual type check to support legacy PHP < 7.1
            throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
        }
        if (!\function_exists('stream_socket_enable_crypto') && !\function_exists('NightwatchAgent_kden27khxA4QoEfj\stream_socket_enable_crypto')) {
            throw new \BadMethodCallException('Encryption not supported on your platform (HHVM < 3.8?)');
            // @codeCoverageIgnore
        }
        // default to empty passphrase to suppress blocking passphrase prompt
        $context += array('passphrase' => '');
        $this->tcp = $tcp;
        $this->encryption = new StreamEncryption($loop ?: Loop::get());
        $this->context = $context;
        $that = $this;
        $this->tcp->on('connection', function ($connection) use ($that) {
            $that->handleConnection($connection);
        });
        $this->tcp->on('error', function ($error) use ($that) {
            $that->emit('error', array($error));
        });
    }
    public function getAddress()
    {
        $address = $this->tcp->getAddress();
        if ($address === null) {
            return null;
        }
        return \str_replace('tcp://', 'tls://', $address);
    }
    public function pause()
    {
        $this->tcp->pause();
    }
    public function resume()
    {
        $this->tcp->resume();
    }
    public function close()
    {
        return $this->tcp->close();
    }
    /** @internal */
    public function handleConnection(ConnectionInterface $connection)
    {
        if (!$connection instanceof Connection) {
            $this->emit('error', array(new \UnexpectedValueException('Base server does not use internal Connection class exposing stream resource')));
            $connection->close();
            return;
        }
        foreach ($this->context as $name => $value) {
            \stream_context_set_option($connection->stream, 'ssl', $name, $value);
        }
        // get remote address before starting TLS handshake in case connection closes during handshake
        $remote = $connection->getRemoteAddress();
        $that = $this;
        $this->encryption->enable($connection)->then(function ($conn) use ($that) {
            $that->emit('connection', array($conn));
        }, function ($error) use ($that, $connection, $remote) {
            $error = new \RuntimeException('Connection from ' . $remote . ' failed during TLS handshake: ' . $error->getMessage(), $error->getCode());
            $that->emit('error', array($error));
            $connection->close();
        });
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Socket;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Loop;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use Exception;
/**
 * @deprecated 1.9.0 See `SocketServer` instead
 * @see SocketServer
 */
final class Server extends EventEmitter implements ServerInterface
{
    private $server;
    /**
     * [Deprecated] `Server`
     *
     * This class exists for BC reasons only and should not be used anymore.
     *
     * ```php
     * // deprecated
     * $socket = new React\Socket\Server(0);
     * $socket = new React\Socket\Server('127.0.0.1:8000');
     * $socket = new React\Socket\Server('127.0.0.1:8000', null, $context);
     * $socket = new React\Socket\Server('127.0.0.1:8000', $loop, $context);
     *
     * // new
     * $socket = new React\Socket\SocketServer('127.0.0.1:0');
     * $socket = new React\Socket\SocketServer('127.0.0.1:8000');
     * $socket = new React\Socket\SocketServer('127.0.0.1:8000', $context);
     * $socket = new React\Socket\SocketServer('127.0.0.1:8000', $context, $loop);
     * ```
     *
     * This class takes an optional `LoopInterface|null $loop` parameter that can be used to
     * pass the event loop instance to use for this object. You can use a `null` value
     * here in order to use the [default loop](https://github.com/reactphp/event-loop#loop).
     * This value SHOULD NOT be given unless you're sure you want to explicitly use a
     * given event loop instance.
     *
     * For BC reasons, you can also pass the TCP socket context options as a simple
     * array without wrapping this in another array under the `tcp` key.
     *
     * @param string|int     $uri
     * @param ?LoopInterface $loop
     * @param array          $context
     * @deprecated 1.9.0 See `SocketServer` instead
     * @see SocketServer
     */
    public function __construct($uri, $loop = null, array $context = array())
    {
        if ($loop !== null && !$loop instanceof LoopInterface) {
            // manual type check to support legacy PHP < 7.1
            throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
        }
        $loop = $loop ?: Loop::get();
        // sanitize TCP context options if not properly wrapped
        if ($context && (!isset($context['tcp']) && !isset($context['tls']) && !isset($context['unix']))) {
            $context = array('tcp' => $context);
        }
        // apply default options if not explicitly given
        $context += array('tcp' => array(), 'tls' => array(), 'unix' => array());
        $scheme = 'tcp';
        $pos = \strpos($uri, '://');
        if ($pos !== \false) {
            $scheme = \substr($uri, 0, $pos);
        }
        if ($scheme === 'unix') {
            $server = new UnixServer($uri, $loop, $context['unix']);
        } else {
            $server = new TcpServer(str_replace('tls://', '', $uri), $loop, $context['tcp']);
            if ($scheme === 'tls') {
                $server = new SecureServer($server, $loop, $context['tls']);
            }
        }
        $this->server = $server;
        $that = $this;
        $server->on('connection', function (ConnectionInterface $conn) use ($that) {
            $that->emit('connection', array($conn));
        });
        $server->on('error', function (Exception $error) use ($that) {
            $that->emit('error', array($error));
        });
    }
    public function getAddress()
    {
        return $this->server->getAddress();
    }
    public function pause()
    {
        $this->server->pause();
    }
    public function resume()
    {
        $this->server->resume();
    }
    public function close()
    {
        $this->server->close();
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Socket;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitterInterface;
/**
 * The `ServerInterface` is responsible for providing an interface for accepting
 * incoming streaming connections, such as a normal TCP/IP connection.
 *
 * Most higher-level components (such as a HTTP server) accept an instance
 * implementing this interface to accept incoming streaming connections.
 * This is usually done via dependency injection, so it's fairly simple to actually
 * swap this implementation against any other implementation of this interface.
 * This means that you SHOULD typehint against this interface instead of a concrete
 * implementation of this interface.
 *
 * Besides defining a few methods, this interface also implements the
 * `EventEmitterInterface` which allows you to react to certain events:
 *
 * connection event:
 *     The `connection` event will be emitted whenever a new connection has been
 *     established, i.e. a new client connects to this server socket:
 *
 *     ```php
 *     $socket->on('connection', function (React\Socket\ConnectionInterface $connection) {
 *         echo 'new connection' . PHP_EOL;
 *     });
 *     ```
 *
 *     See also the `ConnectionInterface` for more details about handling the
 *     incoming connection.
 *
 * error event:
 *     The `error` event will be emitted whenever there's an error accepting a new
 *     connection from a client.
 *
 *     ```php
 *     $socket->on('error', function (Exception $e) {
 *         echo 'error: ' . $e->getMessage() . PHP_EOL;
 *     });
 *     ```
 *
 *     Note that this is not a fatal error event, i.e. the server keeps listening for
 *     new connections even after this event.
 *
 * @see ConnectionInterface
 */
interface ServerInterface extends EventEmitterInterface
{
    /**
     * Returns the full address (URI) this server is currently listening on
     *
     * ```php
     * $address = $socket->getAddress();
     * echo 'Server listening on ' . $address . PHP_EOL;
     * ```
     *
     * If the address can not be determined or is unknown at this time (such as
     * after the socket has been closed), it MAY return a `NULL` value instead.
     *
     * Otherwise, it will return the full address (URI) as a string value, such
     * as `tcp://127.0.0.1:8080`, `tcp://[::1]:80` or `tls://127.0.0.1:443`.
     * Note that individual URI components are application specific and depend
     * on the underlying transport protocol.
     *
     * If this is a TCP/IP based server and you only want the local port, you may
     * use something like this:
     *
     * ```php
     * $address = $socket->getAddress();
     * $port = parse_url($address, PHP_URL_PORT);
     * echo 'Server listening on port ' . $port . PHP_EOL;
     * ```
     *
     * @return ?string the full listening address (URI) or NULL if it is unknown (not applicable to this server socket or already closed)
     */
    public function getAddress();
    /**
     * Pauses accepting new incoming connections.
     *
     * Removes the socket resource from the EventLoop and thus stop accepting
     * new connections. Note that the listening socket stays active and is not
     * closed.
     *
     * This means that new incoming connections will stay pending in the
     * operating system backlog until its configurable backlog is filled.
     * Once the backlog is filled, the operating system may reject further
     * incoming connections until the backlog is drained again by resuming
     * to accept new connections.
     *
     * Once the server is paused, no futher `connection` events SHOULD
     * be emitted.
     *
     * ```php
     * $socket->pause();
     *
     * $socket->on('connection', assertShouldNeverCalled());
     * ```
     *
     * This method is advisory-only, though generally not recommended, the
     * server MAY continue emitting `connection` events.
     *
     * Unless otherwise noted, a successfully opened server SHOULD NOT start
     * in paused state.
     *
     * You can continue processing events by calling `resume()` again.
     *
     * Note that both methods can be called any number of times, in particular
     * calling `pause()` more than once SHOULD NOT have any effect.
     * Similarly, calling this after `close()` is a NO-OP.
     *
     * @see self::resume()
     * @return void
     */
    public function pause();
    /**
     * Resumes accepting new incoming connections.
     *
     * Re-attach the socket resource to the EventLoop after a previous `pause()`.
     *
     * ```php
     * $socket->pause();
     *
     * Loop::addTimer(1.0, function () use ($socket) {
     *     $socket->resume();
     * });
     * ```
     *
     * Note that both methods can be called any number of times, in particular
     * calling `resume()` without a prior `pause()` SHOULD NOT have any effect.
     * Similarly, calling this after `close()` is a NO-OP.
     *
     * @see self::pause()
     * @return void
     */
    public function resume();
    /**
     * Shuts down this listening socket
     *
     * This will stop listening for new incoming connections on this socket.
     *
     * Calling this method more than once on the same instance is a NO-OP.
     *
     * @return void
     */
    public function close();
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Socket;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
final class SocketServer extends EventEmitter implements ServerInterface
{
    private $server;
    /**
     * The `SocketServer` class is the main class in this package that implements the `ServerInterface` and
     * allows you to accept incoming streaming connections, such as plaintext TCP/IP or secure TLS connection streams.
     *
     * ```php
     * $socket = new React\Socket\SocketServer('127.0.0.1:0');
     * $socket = new React\Socket\SocketServer('127.0.0.1:8000');
     * $socket = new React\Socket\SocketServer('127.0.0.1:8000', $context);
     * ```
     *
     * This class takes an optional `LoopInterface|null $loop` parameter that can be used to
     * pass the event loop instance to use for this object. You can use a `null` value
     * here in order to use the [default loop](https://github.com/reactphp/event-loop#loop).
     * This value SHOULD NOT be given unless you're sure you want to explicitly use a
     * given event loop instance.
     *
     * @param string         $uri
     * @param array          $context
     * @param ?LoopInterface $loop
     * @throws \InvalidArgumentException if the listening address is invalid
     * @throws \RuntimeException if listening on this address fails (already in use etc.)
     */
    public function __construct($uri, array $context = array(), $loop = null)
    {
        if ($loop !== null && !$loop instanceof LoopInterface) {
            // manual type check to support legacy PHP < 7.1
            throw new \InvalidArgumentException('Argument #3 ($loop) expected null|React\EventLoop\LoopInterface');
        }
        // apply default options if not explicitly given
        $context += array('tcp' => array(), 'tls' => array(), 'unix' => array());
        $scheme = 'tcp';
        $pos = \strpos($uri, '://');
        if ($pos !== \false) {
            $scheme = \substr($uri, 0, $pos);
        }
        if ($scheme === 'unix') {
            $server = new UnixServer($uri, $loop, $context['unix']);
        } elseif ($scheme === 'php') {
            $server = new FdServer($uri, $loop);
        } else {
            if (preg_match('#^(?:\w+://)?\d+$#', $uri)) {
                throw new \InvalidArgumentException('Invalid URI given (EINVAL)', \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22));
            }
            $server = new TcpServer(str_replace('tls://', '', $uri), $loop, $context['tcp']);
            if ($scheme === 'tls') {
                $server = new SecureServer($server, $loop, $context['tls']);
            }
        }
        $this->server = $server;
        $that = $this;
        $server->on('connection', function (ConnectionInterface $conn) use ($that) {
            $that->emit('connection', array($conn));
        });
        $server->on('error', function (\Exception $error) use ($that) {
            $that->emit('error', array($error));
        });
    }
    public function getAddress()
    {
        return $this->server->getAddress();
    }
    public function pause()
    {
        $this->server->pause();
    }
    public function resume()
    {
        $this->server->resume();
    }
    public function close()
    {
        $this->server->close();
    }
    /**
     * [internal] Internal helper method to accept new connection from given server socket
     *
     * @param resource $socket server socket to accept connection from
     * @return resource new client socket if any
     * @throws \RuntimeException if accepting fails
     * @internal
     */
    public static function accept($socket)
    {
        $errno = 0;
        $errstr = '';
        \set_error_handler(function ($_, $error) use (&$errno, &$errstr) {
            // Match errstr from PHP's warning message.
            // stream_socket_accept(): accept failed: Connection timed out
            $errstr = \preg_replace('#.*: #', '', $error);
            $errno = SocketServer::errno($errstr);
        });
        $newSocket = \stream_socket_accept($socket, 0);
        \restore_error_handler();
        if (\false === $newSocket) {
            throw new \RuntimeException('Unable to accept new connection: ' . $errstr . self::errconst($errno), $errno);
        }
        return $newSocket;
    }
    /**
     * [Internal] Returns errno value for given errstr
     *
     * The errno and errstr values describes the type of error that has been
     * encountered. This method tries to look up the given errstr and find a
     * matching errno value which can be useful to provide more context to error
     * messages. It goes through the list of known errno constants when either
     * `ext-sockets`, `ext-posix` or `ext-pcntl` is available to find an errno
     * matching the given errstr.
     *
     * @param string $errstr
     * @return int errno value (e.g. value of `SOCKET_ECONNREFUSED`) or 0 if not found
     * @internal
     * @copyright Copyright (c) 2023 Christian Lück, taken from https://github.com/clue/errno with permission
     * @codeCoverageIgnore
     */
    public static function errno($errstr)
    {
        // PHP defines the required `strerror()` function through either `ext-sockets`, `ext-posix` or `ext-pcntl`
        $strerror = \function_exists('socket_strerror') ? 'socket_strerror' : (\function_exists('posix_strerror') ? 'posix_strerror' : (\function_exists('pcntl_strerror') ? 'pcntl_strerror' : null));
        if ($strerror !== null) {
            assert(\is_string($strerror) && \is_callable($strerror));
            // PHP defines most useful errno constants like `ECONNREFUSED` through constants in `ext-sockets` like `SOCKET_ECONNREFUSED`
            // PHP also defines a hand full of errno constants like `EMFILE` through constants in `ext-pcntl` like `PCNTL_EMFILE`
            // go through list of all defined constants like `SOCKET_E*` and `PCNTL_E*` and see if they match the given `$errstr`
            foreach (\get_defined_constants(\false) as $name => $value) {
                if (\is_int($value) && (\strpos($name, 'SOCKET_E') === 0 || \strpos($name, 'PCNTL_E') === 0) && $strerror($value) === $errstr) {
                    return $value;
                }
            }
            // if we reach this, no matching errno constant could be found (unlikely when `ext-sockets` is available)
            // go through list of all possible errno values from 1 to `MAX_ERRNO` and see if they match the given `$errstr`
            for ($errno = 1, $max = \defined('MAX_ERRNO') ? \MAX_ERRNO : 4095; $errno <= $max; ++$errno) {
                if ($strerror($errno) === $errstr) {
                    return $errno;
                }
            }
        }
        // if we reach this, no matching errno value could be found (unlikely when either `ext-sockets`, `ext-posix` or `ext-pcntl` is available)
        return 0;
    }
    /**
     * [Internal] Returns errno constant name for given errno value
     *
     * The errno value describes the type of error that has been encountered.
     * This method tries to look up the given errno value and find a matching
     * errno constant name which can be useful to provide more context and more
     * descriptive error messages. It goes through the list of known errno
     * constants when either `ext-sockets` or `ext-pcntl` is available to find
     * the matching errno constant name.
     *
     * Because this method is used to append more context to error messages, the
     * constant name will be prefixed with a space and put between parenthesis
     * when found.
     *
     * @param int $errno
     * @return string e.g. ` (ECONNREFUSED)` or empty string if no matching const for the given errno could be found
     * @internal
     * @copyright Copyright (c) 2023 Christian Lück, taken from https://github.com/clue/errno with permission
     * @codeCoverageIgnore
     */
    public static function errconst($errno)
    {
        // PHP defines most useful errno constants like `ECONNREFUSED` through constants in `ext-sockets` like `SOCKET_ECONNREFUSED`
        // PHP also defines a hand full of errno constants like `EMFILE` through constants in `ext-pcntl` like `PCNTL_EMFILE`
        // go through list of all defined constants like `SOCKET_E*` and `PCNTL_E*` and see if they match the given `$errno`
        foreach (\get_defined_constants(\false) as $name => $value) {
            if ($value === $errno && (\strpos($name, 'SOCKET_E') === 0 || \strpos($name, 'PCNTL_E') === 0)) {
                return ' (' . \substr($name, \strpos($name, '_') + 1) . ')';
            }
        }
        // if we reach this, no matching errno constant could be found (unlikely when `ext-sockets` is available)
        return '';
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Socket;

use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\Deferred;
use RuntimeException;
use UnexpectedValueException;
/**
 * This class is considered internal and its API should not be relied upon
 * outside of Socket.
 *
 * @internal
 */
class StreamEncryption
{
    private $loop;
    private $method;
    private $server;
    public function __construct(LoopInterface $loop, $server = \true)
    {
        $this->loop = $loop;
        $this->server = $server;
        // support TLSv1.0+ by default and exclude legacy SSLv2/SSLv3.
        // As of PHP 7.2+ the main crypto method constant includes all TLS versions.
        // As of PHP 5.6+ the crypto method is a bitmask, so we explicitly include all TLS versions.
        // For legacy PHP < 5.6 the crypto method is a single value only and this constant includes all TLS versions.
        // @link https://3v4l.org/9PSST
        if ($server) {
            $this->method = \STREAM_CRYPTO_METHOD_TLS_SERVER;
            if (\PHP_VERSION_ID < 70200 && \PHP_VERSION_ID >= 50600) {
                $this->method |= \STREAM_CRYPTO_METHOD_TLSv1_0_SERVER | \STREAM_CRYPTO_METHOD_TLSv1_1_SERVER | \STREAM_CRYPTO_METHOD_TLSv1_2_SERVER;
                // @codeCoverageIgnore
            }
        } else {
            $this->method = \STREAM_CRYPTO_METHOD_TLS_CLIENT;
            if (\PHP_VERSION_ID < 70200 && \PHP_VERSION_ID >= 50600) {
                $this->method |= \STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT | \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT | \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
                // @codeCoverageIgnore
            }
        }
    }
    /**
     * @param Connection $stream
     * @return \React\Promise\PromiseInterface<Connection>
     */
    public function enable(Connection $stream)
    {
        return $this->toggle($stream, \true);
    }
    /**
     * @param Connection $stream
     * @param bool $toggle
     * @return \React\Promise\PromiseInterface<Connection>
     */
    public function toggle(Connection $stream, $toggle)
    {
        // pause actual stream instance to continue operation on raw stream socket
        $stream->pause();
        // TODO: add write() event to make sure we're not sending any excessive data
        // cancelling this leaves this stream in an inconsistent state…
        $deferred = new Deferred(function () {
            throw new \RuntimeException();
        });
        // get actual stream socket from stream instance
        $socket = $stream->stream;
        // get crypto method from context options or use global setting from constructor
        $method = $this->method;
        $context = \stream_context_get_options($socket);
        if (isset($context['ssl']['crypto_method'])) {
            $method = $context['ssl']['crypto_method'];
        }
        $that = $this;
        $toggleCrypto = function () use ($socket, $deferred, $toggle, $method, $that) {
            $that->toggleCrypto($socket, $deferred, $toggle, $method);
        };
        $this->loop->addReadStream($socket, $toggleCrypto);
        if (!$this->server) {
            $toggleCrypto();
        }
        $loop = $this->loop;
        return $deferred->promise()->then(function () use ($stream, $socket, $loop, $toggle) {
            $loop->removeReadStream($socket);
            $stream->encryptionEnabled = $toggle;
            $stream->resume();
            return $stream;
        }, function ($error) use ($stream, $socket, $loop) {
            $loop->removeReadStream($socket);
            $stream->resume();
            throw $error;
        });
    }
    /**
     * @internal
     * @param resource $socket
     * @param Deferred<null> $deferred
     * @param bool $toggle
     * @param int $method
     * @return void
     */
    public function toggleCrypto($socket, Deferred $deferred, $toggle, $method)
    {
        $error = null;
        \set_error_handler(function ($_, $errstr) use (&$error) {
            $error = \str_replace(array("\r", "\n"), ' ', $errstr);
            // remove useless function name from error message
            if (($pos = \strpos($error, "): ")) !== \false) {
                $error = \substr($error, $pos + 3);
            }
        });
        $result = \stream_socket_enable_crypto($socket, $toggle, $method);
        \restore_error_handler();
        if (\true === $result) {
            $deferred->resolve(null);
        } else if (\false === $result) {
            // overwrite callback arguments for PHP7+ only, so they do not show
            // up in the Exception trace and do not cause a possible cyclic reference.
            $d = $deferred;
            $deferred = null;
            if (\feof($socket) || $error === null) {
                // EOF or failed without error => connection closed during handshake
                $d->reject(new \UnexpectedValueException('Connection lost during TLS handshake (ECONNRESET)', \defined('SOCKET_ECONNRESET') ? \SOCKET_ECONNRESET : 104));
            } else {
                // handshake failed with error message
                $d->reject(new \UnexpectedValueException($error));
            }
        } else {
            // need more data, will retry
        }
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Socket;

use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Loop;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise;
use InvalidArgumentException;
use RuntimeException;
final class TcpConnector implements ConnectorInterface
{
    private $loop;
    private $context;
    /**
     * @param ?LoopInterface $loop
     * @param array $context
     */
    public function __construct($loop = null, array $context = array())
    {
        if ($loop !== null && !$loop instanceof LoopInterface) {
            // manual type check to support legacy PHP < 7.1
            throw new \InvalidArgumentException('Argument #1 ($loop) expected null|React\EventLoop\LoopInterface');
        }
        $this->loop = $loop ?: Loop::get();
        $this->context = $context;
    }
    public function connect($uri)
    {
        if (\strpos($uri, '://') === \false) {
            $uri = 'tcp://' . $uri;
        }
        $parts = \parse_url($uri);
        if (!$parts || !isset($parts['scheme'], $parts['host'], $parts['port']) || $parts['scheme'] !== 'tcp') {
            return Promise\reject(new \InvalidArgumentException('Given URI "' . $uri . '" is invalid (EINVAL)', \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22)));
        }
        $ip = \trim($parts['host'], '[]');
        if (@\inet_pton($ip) === \false) {
            return Promise\reject(new \InvalidArgumentException('Given URI "' . $uri . '" does not contain a valid host IP (EINVAL)', \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22)));
        }
        // use context given in constructor
        $context = array('socket' => $this->context);
        // parse arguments from query component of URI
        $args = array();
        if (isset($parts['query'])) {
            \parse_str($parts['query'], $args);
        }
        // If an original hostname has been given, use this for TLS setup.
        // This can happen due to layers of nested connectors, such as a
        // DnsConnector reporting its original hostname.
        // These context options are here in case TLS is enabled later on this stream.
        // If TLS is not enabled later, this doesn't hurt either.
        if (isset($args['hostname'])) {
            $context['ssl'] = array('SNI_enabled' => \true, 'peer_name' => $args['hostname']);
            // Legacy PHP < 5.6 ignores peer_name and requires legacy context options instead.
            // The SNI_server_name context option has to be set here during construction,
            // as legacy PHP ignores any values set later.
            // @codeCoverageIgnoreStart
            if (\PHP_VERSION_ID < 50600) {
                $context['ssl'] += array('SNI_server_name' => $args['hostname'], 'CN_match' => $args['hostname']);
            }
            // @codeCoverageIgnoreEnd
        }
        // latest versions of PHP no longer accept any other URI components and
        // HHVM fails to parse URIs with a query but no path, so let's simplify our URI here
        $remote = 'tcp://' . $parts['host'] . ':' . $parts['port'];
        $stream = @\stream_socket_client($remote, $errno, $errstr, 0, \STREAM_CLIENT_CONNECT | \STREAM_CLIENT_ASYNC_CONNECT, \stream_context_create($context));
        if (\false === $stream) {
            return Promise\reject(new \RuntimeException('Connection to ' . $uri . ' failed: ' . $errstr . SocketServer::errconst($errno), $errno));
        }
        // wait for connection
        $loop = $this->loop;
        return new Promise\Promise(function ($resolve, $reject) use ($loop, $stream, $uri) {
            $loop->addWriteStream($stream, function ($stream) use ($loop, $resolve, $reject, $uri) {
                $loop->removeWriteStream($stream);
                // The following hack looks like the only way to
                // detect connection refused errors with PHP's stream sockets.
                if (\false === \stream_socket_get_name($stream, \true)) {
                    // If we reach this point, we know the connection is dead, but we don't know the underlying error condition.
                    // @codeCoverageIgnoreStart
                    if (\function_exists('socket_import_stream')) {
                        // actual socket errno and errstr can be retrieved with ext-sockets on PHP 5.4+
                        $socket = \socket_import_stream($stream);
                        $errno = \socket_get_option($socket, \SOL_SOCKET, \SO_ERROR);
                        $errstr = \socket_strerror($errno);
                    } elseif (\PHP_OS === 'Linux') {
                        // Linux reports socket errno and errstr again when trying to write to the dead socket.
                        // Suppress error reporting to get error message below and close dead socket before rejecting.
                        // This is only known to work on Linux, Mac and Windows are known to not support this.
                        $errno = 0;
                        $errstr = '';
                        \set_error_handler(function ($_, $error) use (&$errno, &$errstr) {
                            // Match errstr from PHP's warning message.
                            // fwrite(): send of 1 bytes failed with errno=111 Connection refused
                            \preg_match('/errno=(\d+) (.+)/', $error, $m);
                            $errno = isset($m[1]) ? (int) $m[1] : 0;
                            $errstr = isset($m[2]) ? $m[2] : $error;
                        });
                        \fwrite($stream, \PHP_EOL);
                        \restore_error_handler();
                    } else {
                        // Not on Linux and ext-sockets not available? Too bad.
                        $errno = \defined('SOCKET_ECONNREFUSED') ? \SOCKET_ECONNREFUSED : 111;
                        $errstr = 'Connection refused?';
                    }
                    // @codeCoverageIgnoreEnd
                    \fclose($stream);
                    $reject(new \RuntimeException('Connection to ' . $uri . ' failed: ' . $errstr . SocketServer::errconst($errno), $errno));
                } else {
                    $resolve(new Connection($stream, $loop));
                }
            });
        }, function () use ($loop, $stream, $uri) {
            $loop->removeWriteStream($stream);
            \fclose($stream);
            // @codeCoverageIgnoreStart
            // legacy PHP 5.3 sometimes requires a second close call (see tests)
            if (\PHP_VERSION_ID < 50400 && \is_resource($stream)) {
                \fclose($stream);
            }
            // @codeCoverageIgnoreEnd
            throw new \RuntimeException('Connection to ' . $uri . ' cancelled during TCP/IP handshake (ECONNABORTED)', \defined('SOCKET_ECONNABORTED') ? \SOCKET_ECONNABORTED : 103);
        });
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Socket;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Loop;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use InvalidArgumentException;
use RuntimeException;
/**
 * The `TcpServer` class implements the `ServerInterface` and
 * is responsible for accepting plaintext TCP/IP connections.
 *
 * ```php
 * $server = new React\Socket\TcpServer(8080);
 * ```
 *
 * Whenever a client connects, it will emit a `connection` event with a connection
 * instance implementing `ConnectionInterface`:
 *
 * ```php
 * $server->on('connection', function (React\Socket\ConnectionInterface $connection) {
 *     echo 'Plaintext connection from ' . $connection->getRemoteAddress() . PHP_EOL;
 *     $connection->write('hello there!' . PHP_EOL);
 *     …
 * });
 * ```
 *
 * See also the `ServerInterface` for more details.
 *
 * @see ServerInterface
 * @see ConnectionInterface
 */
final class TcpServer extends EventEmitter implements ServerInterface
{
    private $master;
    private $loop;
    private $listening = \false;
    /**
     * Creates a plaintext TCP/IP socket server and starts listening on the given address
     *
     * This starts accepting new incoming connections on the given address.
     * See also the `connection event` documented in the `ServerInterface`
     * for more details.
     *
     * ```php
     * $server = new React\Socket\TcpServer(8080);
     * ```
     *
     * As above, the `$uri` parameter can consist of only a port, in which case the
     * server will default to listening on the localhost address `127.0.0.1`,
     * which means it will not be reachable from outside of this system.
     *
     * In order to use a random port assignment, you can use the port `0`:
     *
     * ```php
     * $server = new React\Socket\TcpServer(0);
     * $address = $server->getAddress();
     * ```
     *
     * In order to change the host the socket is listening on, you can provide an IP
     * address through the first parameter provided to the constructor, optionally
     * preceded by the `tcp://` scheme:
     *
     * ```php
     * $server = new React\Socket\TcpServer('192.168.0.1:8080');
     * ```
     *
     * If you want to listen on an IPv6 address, you MUST enclose the host in square
     * brackets:
     *
     * ```php
     * $server = new React\Socket\TcpServer('[::1]:8080');
     * ```
     *
     * If the given URI is invalid, does not contain a port, any other scheme or if it
     * contains a hostname, it will throw an `InvalidArgumentException`:
     *
     * ```php
     * // throws InvalidArgumentException due to missing port
     * $server = new React\Socket\TcpServer('127.0.0.1');
     * ```
     *
     * If the given URI appears to be valid, but listening on it fails (such as if port
     * is already in use or port below 1024 may require root access etc.), it will
     * throw a `RuntimeException`:
     *
     * ```php
     * $first = new React\Socket\TcpServer(8080);
     *
     * // throws RuntimeException because port is already in use
     * $second = new React\Socket\TcpServer(8080);
     * ```
     *
     * Note that these error conditions may vary depending on your system and/or
     * configuration.
     * See the exception message and code for more details about the actual error
     * condition.
     *
     * This class takes an optional `LoopInterface|null $loop` parameter that can be used to
     * pass the event loop instance to use for this object. You can use a `null` value
     * here in order to use the [default loop](https://github.com/reactphp/event-loop#loop).
     * This value SHOULD NOT be given unless you're sure you want to explicitly use a
     * given event loop instance.
     *
     * Optionally, you can specify [socket context options](https://www.php.net/manual/en/context.socket.php)
     * for the underlying stream socket resource like this:
     *
     * ```php
     * $server = new React\Socket\TcpServer('[::1]:8080', null, array(
     *     'backlog' => 200,
     *     'so_reuseport' => true,
     *     'ipv6_v6only' => true
     * ));
     * ```
     *
     * Note that available [socket context options](https://www.php.net/manual/en/context.socket.php),
     * their defaults and effects of changing these may vary depending on your system
     * and/or PHP version.
     * Passing unknown context options has no effect.
     * The `backlog` context option defaults to `511` unless given explicitly.
     *
     * @param string|int     $uri
     * @param ?LoopInterface $loop
     * @param array          $context
     * @throws InvalidArgumentException if the listening address is invalid
     * @throws RuntimeException if listening on this address fails (already in use etc.)
     */
    public function __construct($uri, $loop = null, array $context = array())
    {
        if ($loop !== null && !$loop instanceof LoopInterface) {
            // manual type check to support legacy PHP < 7.1
            throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
        }
        $this->loop = $loop ?: Loop::get();
        // a single port has been given => assume localhost
        if ((string) (int) $uri === (string) $uri) {
            $uri = '127.0.0.1:' . $uri;
        }
        // assume default scheme if none has been given
        if (\strpos($uri, '://') === \false) {
            $uri = 'tcp://' . $uri;
        }
        // parse_url() does not accept null ports (random port assignment) => manually remove
        if (\substr($uri, -2) === ':0') {
            $parts = \parse_url(\substr($uri, 0, -2));
            if ($parts) {
                $parts['port'] = 0;
            }
        } else {
            $parts = \parse_url($uri);
        }
        // ensure URI contains TCP scheme, host and port
        if (!$parts || !isset($parts['scheme'], $parts['host'], $parts['port']) || $parts['scheme'] !== 'tcp') {
            throw new \InvalidArgumentException('Invalid URI "' . $uri . '" given (EINVAL)', \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22));
        }
        if (@\inet_pton(\trim($parts['host'], '[]')) === \false) {
            throw new \InvalidArgumentException('Given URI "' . $uri . '" does not contain a valid host IP (EINVAL)', \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22));
        }
        $this->master = @\stream_socket_server($uri, $errno, $errstr, \STREAM_SERVER_BIND | \STREAM_SERVER_LISTEN, \stream_context_create(array('socket' => $context + array('backlog' => 511))));
        if (\false === $this->master) {
            if ($errno === 0) {
                // PHP does not seem to report errno, so match errno from errstr
                // @link https://3v4l.org/3qOBl
                $errno = SocketServer::errno($errstr);
            }
            throw new \RuntimeException('Failed to listen on "' . $uri . '": ' . $errstr . SocketServer::errconst($errno), $errno);
        }
        \stream_set_blocking($this->master, \false);
        $this->resume();
    }
    public function getAddress()
    {
        if (!\is_resource($this->master)) {
            return null;
        }
        $address = \stream_socket_get_name($this->master, \false);
        // check if this is an IPv6 address which includes multiple colons but no square brackets
        $pos = \strrpos($address, ':');
        if ($pos !== \false && \strpos($address, ':') < $pos && \substr($address, 0, 1) !== '[') {
            $address = '[' . \substr($address, 0, $pos) . ']:' . \substr($address, $pos + 1);
            // @codeCoverageIgnore
        }
        return 'tcp://' . $address;
    }
    public function pause()
    {
        if (!$this->listening) {
            return;
        }
        $this->loop->removeReadStream($this->master);
        $this->listening = \false;
    }
    public function resume()
    {
        if ($this->listening || !\is_resource($this->master)) {
            return;
        }
        $that = $this;
        $this->loop->addReadStream($this->master, function ($master) use ($that) {
            try {
                $newSocket = SocketServer::accept($master);
            } catch (\RuntimeException $e) {
                $that->emit('error', array($e));
                return;
            }
            $that->handleConnection($newSocket);
        });
        $this->listening = \true;
    }
    public function close()
    {
        if (!\is_resource($this->master)) {
            return;
        }
        $this->pause();
        \fclose($this->master);
        $this->removeAllListeners();
    }
    /** @internal */
    public function handleConnection($socket)
    {
        $this->emit('connection', array(new Connection($socket, $this->loop)));
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Socket;

use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Loop;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise\Promise;
final class TimeoutConnector implements ConnectorInterface
{
    private $connector;
    private $timeout;
    private $loop;
    /**
     * @param ConnectorInterface $connector
     * @param float $timeout
     * @param ?LoopInterface $loop
     */
    public function __construct(ConnectorInterface $connector, $timeout, $loop = null)
    {
        if ($loop !== null && !$loop instanceof LoopInterface) {
            // manual type check to support legacy PHP < 7.1
            throw new \InvalidArgumentException('Argument #3 ($loop) expected null|React\EventLoop\LoopInterface');
        }
        $this->connector = $connector;
        $this->timeout = $timeout;
        $this->loop = $loop ?: Loop::get();
    }
    public function connect($uri)
    {
        $promise = $this->connector->connect($uri);
        $loop = $this->loop;
        $time = $this->timeout;
        return new Promise(function ($resolve, $reject) use ($loop, $time, $promise, $uri) {
            $timer = null;
            $promise = $promise->then(function ($v) use (&$timer, $loop, $resolve) {
                if ($timer) {
                    $loop->cancelTimer($timer);
                }
                $timer = \false;
                $resolve($v);
            }, function ($v) use (&$timer, $loop, $reject) {
                if ($timer) {
                    $loop->cancelTimer($timer);
                }
                $timer = \false;
                $reject($v);
            });
            // promise already resolved => no need to start timer
            if ($timer === \false) {
                return;
            }
            // start timeout timer which will cancel the pending promise
            $timer = $loop->addTimer($time, function () use ($time, &$promise, $reject, $uri) {
                $reject(new \RuntimeException('Connection to ' . $uri . ' timed out after ' . $time . ' seconds (ETIMEDOUT)', \defined('SOCKET_ETIMEDOUT') ? \SOCKET_ETIMEDOUT : 110));
                // Cancel pending connection to clean up any underlying resources and references.
                // Avoid garbage references in call stack by passing pending promise by reference.
                assert(\method_exists($promise, 'cancel'));
                $promise->cancel();
                $promise = null;
            });
        }, function () use (&$promise) {
            // Cancelling this promise will cancel the pending connection, thus triggering the rejection logic above.
            // Avoid garbage references in call stack by passing pending promise by reference.
            assert(\method_exists($promise, 'cancel'));
            $promise->cancel();
            $promise = null;
        });
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Socket;

use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Loop;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use NightwatchAgent_kden27khxA4QoEfj\React\Promise;
use InvalidArgumentException;
use RuntimeException;
/**
 * Unix domain socket connector
 *
 * Unix domain sockets use atomic operations, so we can as well emulate
 * async behavior.
 */
final class UnixConnector implements ConnectorInterface
{
    private $loop;
    /**
     * @param ?LoopInterface $loop
     */
    public function __construct($loop = null)
    {
        if ($loop !== null && !$loop instanceof LoopInterface) {
            // manual type check to support legacy PHP < 7.1
            throw new \InvalidArgumentException('Argument #1 ($loop) expected null|React\EventLoop\LoopInterface');
        }
        $this->loop = $loop ?: Loop::get();
    }
    public function connect($path)
    {
        if (\strpos($path, '://') === \false) {
            $path = 'unix://' . $path;
        } elseif (\substr($path, 0, 7) !== 'unix://') {
            return Promise\reject(new \InvalidArgumentException('Given URI "' . $path . '" is invalid (EINVAL)', \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22)));
        }
        $resource = @\stream_socket_client($path, $errno, $errstr, 1.0);
        if (!$resource) {
            return Promise\reject(new \RuntimeException('Unable to connect to unix domain socket "' . $path . '": ' . $errstr . SocketServer::errconst($errno), $errno));
        }
        $connection = new Connection($resource, $this->loop);
        $connection->unix = \true;
        return Promise\resolve($connection);
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Socket;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Loop;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use InvalidArgumentException;
use RuntimeException;
/**
 * The `UnixServer` class implements the `ServerInterface` and
 * is responsible for accepting plaintext connections on unix domain sockets.
 *
 * ```php
 * $server = new React\Socket\UnixServer('unix:///tmp/app.sock');
 * ```
 *
 * See also the `ServerInterface` for more details.
 *
 * @see ServerInterface
 * @see ConnectionInterface
 */
final class UnixServer extends EventEmitter implements ServerInterface
{
    private $master;
    private $loop;
    private $listening = \false;
    /**
     * Creates a plaintext socket server and starts listening on the given unix socket
     *
     * This starts accepting new incoming connections on the given address.
     * See also the `connection event` documented in the `ServerInterface`
     * for more details.
     *
     * ```php
     * $server = new React\Socket\UnixServer('unix:///tmp/app.sock');
     * ```
     *
     * This class takes an optional `LoopInterface|null $loop` parameter that can be used to
     * pass the event loop instance to use for this object. You can use a `null` value
     * here in order to use the [default loop](https://github.com/reactphp/event-loop#loop).
     * This value SHOULD NOT be given unless you're sure you want to explicitly use a
     * given event loop instance.
     *
     * @param string         $path
     * @param ?LoopInterface $loop
     * @param array          $context
     * @throws InvalidArgumentException if the listening address is invalid
     * @throws RuntimeException if listening on this address fails (already in use etc.)
     */
    public function __construct($path, $loop = null, array $context = array())
    {
        if ($loop !== null && !$loop instanceof LoopInterface) {
            // manual type check to support legacy PHP < 7.1
            throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
        }
        $this->loop = $loop ?: Loop::get();
        if (\strpos($path, '://') === \false) {
            $path = 'unix://' . $path;
        } elseif (\substr($path, 0, 7) !== 'unix://') {
            throw new \InvalidArgumentException('Given URI "' . $path . '" is invalid (EINVAL)', \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22));
        }
        $errno = 0;
        $errstr = '';
        \set_error_handler(function ($_, $error) use (&$errno, &$errstr) {
            // PHP does not seem to report errno/errstr for Unix domain sockets (UDS) right now.
            // This only applies to UDS server sockets, see also https://3v4l.org/NAhpr.
            // Parse PHP warning message containing unknown error, HHVM reports proper info at least.
            if (\preg_match('/\(([^\)]+)\)|\[(\d+)\]: (.*)/', $error, $match)) {
                $errstr = isset($match[3]) ? $match['3'] : $match[1];
                $errno = isset($match[2]) ? (int) $match[2] : 0;
            }
        });
        $this->master = \stream_socket_server($path, $errno, $errstr, \STREAM_SERVER_BIND | \STREAM_SERVER_LISTEN, \stream_context_create(array('socket' => $context)));
        \restore_error_handler();
        if (\false === $this->master) {
            throw new \RuntimeException('Failed to listen on Unix domain socket "' . $path . '": ' . $errstr . SocketServer::errconst($errno), $errno);
        }
        \stream_set_blocking($this->master, 0);
        $this->resume();
    }
    public function getAddress()
    {
        if (!\is_resource($this->master)) {
            return null;
        }
        return 'unix://' . \stream_socket_get_name($this->master, \false);
    }
    public function pause()
    {
        if (!$this->listening) {
            return;
        }
        $this->loop->removeReadStream($this->master);
        $this->listening = \false;
    }
    public function resume()
    {
        if ($this->listening || !is_resource($this->master)) {
            return;
        }
        $that = $this;
        $this->loop->addReadStream($this->master, function ($master) use ($that) {
            try {
                $newSocket = SocketServer::accept($master);
            } catch (\RuntimeException $e) {
                $that->emit('error', array($e));
                return;
            }
            $that->handleConnection($newSocket);
        });
        $this->listening = \true;
    }
    public function close()
    {
        if (!\is_resource($this->master)) {
            return;
        }
        $this->pause();
        \fclose($this->master);
        $this->removeAllListeners();
    }
    /** @internal */
    public function handleConnection($socket)
    {
        $connection = new Connection($socket, $this->loop);
        $connection->unix = \true;
        $this->emit('connection', array($connection));
    }
}
The MIT License (MIT)

Copyright (c) 2012 Christian Lück, Cees-Jan Kiewiet, Jan Sorgalla, Chris Boden, Igor Wiedler

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Stream;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
final class CompositeStream extends EventEmitter implements DuplexStreamInterface
{
    private $readable;
    private $writable;
    private $closed = \false;
    public function __construct(ReadableStreamInterface $readable, WritableStreamInterface $writable)
    {
        $this->readable = $readable;
        $this->writable = $writable;
        if (!$readable->isReadable() || !$writable->isWritable()) {
            $this->close();
            return;
        }
        Util::forwardEvents($this->readable, $this, array('data', 'end', 'error'));
        Util::forwardEvents($this->writable, $this, array('drain', 'error', 'pipe'));
        $this->readable->on('close', array($this, 'close'));
        $this->writable->on('close', array($this, 'close'));
    }
    public function isReadable()
    {
        return $this->readable->isReadable();
    }
    public function pause()
    {
        $this->readable->pause();
    }
    public function resume()
    {
        if (!$this->writable->isWritable()) {
            return;
        }
        $this->readable->resume();
    }
    public function pipe(WritableStreamInterface $dest, array $options = array())
    {
        return Util::pipe($this, $dest, $options);
    }
    public function isWritable()
    {
        return $this->writable->isWritable();
    }
    public function write($data)
    {
        return $this->writable->write($data);
    }
    public function end($data = null)
    {
        $this->readable->pause();
        $this->writable->end($data);
    }
    public function close()
    {
        if ($this->closed) {
            return;
        }
        $this->closed = \true;
        $this->readable->close();
        $this->writable->close();
        $this->emit('close');
        $this->removeAllListeners();
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Stream;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Loop;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use InvalidArgumentException;
final class DuplexResourceStream extends EventEmitter implements DuplexStreamInterface
{
    private $stream;
    /** @var LoopInterface */
    private $loop;
    /**
     * Controls the maximum buffer size in bytes to read at once from the stream.
     *
     * This can be a positive number which means that up to X bytes will be read
     * at once from the underlying stream resource. Note that the actual number
     * of bytes read may be lower if the stream resource has less than X bytes
     * currently available.
     *
     * This can be `-1` which means read everything available from the
     * underlying stream resource.
     * This should read until the stream resource is not readable anymore
     * (i.e. underlying buffer drained), note that this does not neccessarily
     * mean it reached EOF.
     *
     * @var int
     */
    private $bufferSize;
    private $buffer;
    private $readable = \true;
    private $writable = \true;
    private $closing = \false;
    private $listening = \false;
    /**
     * @param resource $stream
     * @param ?LoopInterface $loop
     * @param ?int $readChunkSize
     * @param ?WritableStreamInterface $buffer
     */
    public function __construct($stream, $loop = null, $readChunkSize = null, $buffer = null)
    {
        if (!\is_resource($stream) || \get_resource_type($stream) !== "stream") {
            throw new InvalidArgumentException('First parameter must be a valid stream resource');
        }
        // ensure resource is opened for reading and wrting (fopen mode must contain "+")
        $meta = \stream_get_meta_data($stream);
        if (isset($meta['mode']) && $meta['mode'] !== '' && \strpos($meta['mode'], '+') === \false) {
            throw new InvalidArgumentException('Given stream resource is not opened in read and write mode');
        }
        // this class relies on non-blocking I/O in order to not interrupt the event loop
        // e.g. pipes on Windows do not support this: https://bugs.php.net/bug.php?id=47918
        if ($buffer !== null && !$buffer instanceof WritableResourceStream && \stream_set_blocking($stream, \false) !== \true) {
            throw new \RuntimeException('Unable to set stream resource to non-blocking mode');
        }
        if ($loop !== null && !$loop instanceof LoopInterface) {
            // manual type check to support legacy PHP < 7.1
            throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
        }
        if ($buffer !== null && !$buffer instanceof WritableStreamInterface) {
            // manual type check to support legacy PHP < 7.1
            throw new \InvalidArgumentException('Argument #4 ($buffer) expected null|React\Stream\WritableStreamInterface');
        }
        // Use unbuffered read operations on the underlying stream resource.
        // Reading chunks from the stream may otherwise leave unread bytes in
        // PHP's stream buffers which some event loop implementations do not
        // trigger events on (edge triggered).
        // This does not affect the default event loop implementation (level
        // triggered), so we can ignore platforms not supporting this (HHVM).
        // Pipe streams (such as STDIN) do not seem to require this and legacy
        // PHP versions cause SEGFAULTs on unbuffered pipe streams, so skip this.
        if (\function_exists('stream_set_read_buffer') && !$this->isLegacyPipe($stream)) {
            \stream_set_read_buffer($stream, 0);
        }
        if ($buffer === null) {
            $buffer = new WritableResourceStream($stream, $loop);
        }
        $this->stream = $stream;
        $this->loop = $loop ?: Loop::get();
        $this->bufferSize = $readChunkSize === null ? 65536 : (int) $readChunkSize;
        $this->buffer = $buffer;
        $that = $this;
        $this->buffer->on('error', function ($error) use ($that) {
            $that->emit('error', array($error));
        });
        $this->buffer->on('close', array($this, 'close'));
        $this->buffer->on('drain', function () use ($that) {
            $that->emit('drain');
        });
        $this->resume();
    }
    public function isReadable()
    {
        return $this->readable;
    }
    public function isWritable()
    {
        return $this->writable;
    }
    public function pause()
    {
        if ($this->listening) {
            $this->loop->removeReadStream($this->stream);
            $this->listening = \false;
        }
    }
    public function resume()
    {
        if (!$this->listening && $this->readable) {
            $this->loop->addReadStream($this->stream, array($this, 'handleData'));
            $this->listening = \true;
        }
    }
    public function write($data)
    {
        if (!$this->writable) {
            return \false;
        }
        return $this->buffer->write($data);
    }
    public function close()
    {
        if (!$this->writable && !$this->closing) {
            return;
        }
        $this->closing = \false;
        $this->readable = \false;
        $this->writable = \false;
        $this->emit('close');
        $this->pause();
        $this->buffer->close();
        $this->removeAllListeners();
        if (\is_resource($this->stream)) {
            \fclose($this->stream);
        }
    }
    public function end($data = null)
    {
        if (!$this->writable) {
            return;
        }
        $this->closing = \true;
        $this->readable = \false;
        $this->writable = \false;
        $this->pause();
        $this->buffer->end($data);
    }
    public function pipe(WritableStreamInterface $dest, array $options = array())
    {
        return Util::pipe($this, $dest, $options);
    }
    /** @internal */
    public function handleData($stream)
    {
        $error = null;
        \set_error_handler(function ($errno, $errstr, $errfile, $errline) use (&$error) {
            $error = new \ErrorException($errstr, 0, $errno, $errfile, $errline);
        });
        $data = \stream_get_contents($stream, $this->bufferSize);
        \restore_error_handler();
        if ($error !== null) {
            $this->emit('error', array(new \RuntimeException('Unable to read from stream: ' . $error->getMessage(), 0, $error)));
            $this->close();
            return;
        }
        if ($data !== '') {
            $this->emit('data', array($data));
        } elseif (\feof($this->stream)) {
            // no data read => we reached the end and close the stream
            $this->emit('end');
            $this->close();
        }
    }
    /**
     * Returns whether this is a pipe resource in a legacy environment
     *
     * This works around a legacy PHP bug (#61019) that was fixed in PHP 5.4.28+
     * and PHP 5.5.12+ and newer.
     *
     * @param resource $resource
     * @return bool
     * @link https://github.com/reactphp/child-process/issues/40
     *
     * @codeCoverageIgnore
     */
    private function isLegacyPipe($resource)
    {
        if (\PHP_VERSION_ID < 50428 || \PHP_VERSION_ID >= 50500 && \PHP_VERSION_ID < 50512) {
            $meta = \stream_get_meta_data($resource);
            if (isset($meta['stream_type']) && $meta['stream_type'] === 'STDIO') {
                return \true;
            }
        }
        return \false;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Stream;

/**
 * The `DuplexStreamInterface` is responsible for providing an interface for
 * duplex streams (both readable and writable).
 *
 * It builds on top of the existing interfaces for readable and writable streams
 * and follows the exact same method and event semantics.
 * If you're new to this concept, you should look into the
 * `ReadableStreamInterface` and `WritableStreamInterface` first.
 *
 * Besides defining a few methods, this interface also implements the
 * `EventEmitterInterface` which allows you to react to the same events defined
 * on the `ReadbleStreamInterface` and `WritableStreamInterface`.
 *
 * The event callback functions MUST be a valid `callable` that obeys strict
 * parameter definitions and MUST accept event parameters exactly as documented.
 * The event callback functions MUST NOT throw an `Exception`.
 * The return value of the event callback functions will be ignored and has no
 * effect, so for performance reasons you're recommended to not return any
 * excessive data structures.
 *
 * Every implementation of this interface MUST follow these event semantics in
 * order to be considered a well-behaving stream.
 *
 * > Note that higher-level implementations of this interface may choose to
 *   define additional events with dedicated semantics not defined as part of
 *   this low-level stream specification. Conformance with these event semantics
 *   is out of scope for this interface, so you may also have to refer to the
 *   documentation of such a higher-level implementation.
 *
 * @see ReadableStreamInterface
 * @see WritableStreamInterface
 */
interface DuplexStreamInterface extends ReadableStreamInterface, WritableStreamInterface
{
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Stream;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Loop;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
use InvalidArgumentException;
final class ReadableResourceStream extends EventEmitter implements ReadableStreamInterface
{
    /**
     * @var resource
     */
    private $stream;
    /** @var LoopInterface */
    private $loop;
    /**
     * Controls the maximum buffer size in bytes to read at once from the stream.
     *
     * This value SHOULD NOT be changed unless you know what you're doing.
     *
     * This can be a positive number which means that up to X bytes will be read
     * at once from the underlying stream resource. Note that the actual number
     * of bytes read may be lower if the stream resource has less than X bytes
     * currently available.
     *
     * This can be `-1` which means read everything available from the
     * underlying stream resource.
     * This should read until the stream resource is not readable anymore
     * (i.e. underlying buffer drained), note that this does not neccessarily
     * mean it reached EOF.
     *
     * @var int
     */
    private $bufferSize;
    private $closed = \false;
    private $listening = \false;
    /**
     * @param resource $stream
     * @param ?LoopInterface $loop
     * @param ?int $readChunkSize
     */
    public function __construct($stream, $loop = null, $readChunkSize = null)
    {
        if (!\is_resource($stream) || \get_resource_type($stream) !== "stream") {
            throw new InvalidArgumentException('First parameter must be a valid stream resource');
        }
        // ensure resource is opened for reading (fopen mode must contain "r" or "+")
        $meta = \stream_get_meta_data($stream);
        if (isset($meta['mode']) && $meta['mode'] !== '' && \strpos($meta['mode'], 'r') === \strpos($meta['mode'], '+')) {
            throw new InvalidArgumentException('Given stream resource is not opened in read mode');
        }
        // this class relies on non-blocking I/O in order to not interrupt the event loop
        // e.g. pipes on Windows do not support this: https://bugs.php.net/bug.php?id=47918
        if (\stream_set_blocking($stream, \false) !== \true) {
            throw new \RuntimeException('Unable to set stream resource to non-blocking mode');
        }
        if ($loop !== null && !$loop instanceof LoopInterface) {
            // manual type check to support legacy PHP < 7.1
            throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
        }
        // Use unbuffered read operations on the underlying stream resource.
        // Reading chunks from the stream may otherwise leave unread bytes in
        // PHP's stream buffers which some event loop implementations do not
        // trigger events on (edge triggered).
        // This does not affect the default event loop implementation (level
        // triggered), so we can ignore platforms not supporting this (HHVM).
        // Pipe streams (such as STDIN) do not seem to require this and legacy
        // PHP versions cause SEGFAULTs on unbuffered pipe streams, so skip this.
        if (\function_exists('stream_set_read_buffer') && !$this->isLegacyPipe($stream)) {
            \stream_set_read_buffer($stream, 0);
        }
        $this->stream = $stream;
        $this->loop = $loop ?: Loop::get();
        $this->bufferSize = $readChunkSize === null ? 65536 : (int) $readChunkSize;
        $this->resume();
    }
    public function isReadable()
    {
        return !$this->closed;
    }
    public function pause()
    {
        if ($this->listening) {
            $this->loop->removeReadStream($this->stream);
            $this->listening = \false;
        }
    }
    public function resume()
    {
        if (!$this->listening && !$this->closed) {
            $this->loop->addReadStream($this->stream, array($this, 'handleData'));
            $this->listening = \true;
        }
    }
    public function pipe(WritableStreamInterface $dest, array $options = array())
    {
        return Util::pipe($this, $dest, $options);
    }
    public function close()
    {
        if ($this->closed) {
            return;
        }
        $this->closed = \true;
        $this->emit('close');
        $this->pause();
        $this->removeAllListeners();
        if (\is_resource($this->stream)) {
            \fclose($this->stream);
        }
    }
    /** @internal */
    public function handleData()
    {
        $error = null;
        \set_error_handler(function ($errno, $errstr, $errfile, $errline) use (&$error) {
            $error = new \ErrorException($errstr, 0, $errno, $errfile, $errline);
        });
        $data = \stream_get_contents($this->stream, $this->bufferSize);
        \restore_error_handler();
        if ($error !== null) {
            $this->emit('error', array(new \RuntimeException('Unable to read from stream: ' . $error->getMessage(), 0, $error)));
            $this->close();
            return;
        }
        if ($data !== '') {
            $this->emit('data', array($data));
        } elseif (\feof($this->stream)) {
            // no data read => we reached the end and close the stream
            $this->emit('end');
            $this->close();
        }
    }
    /**
     * Returns whether this is a pipe resource in a legacy environment
     *
     * This works around a legacy PHP bug (#61019) that was fixed in PHP 5.4.28+
     * and PHP 5.5.12+ and newer.
     *
     * @param resource $resource
     * @return bool
     * @link https://github.com/reactphp/child-process/issues/40
     *
     * @codeCoverageIgnore
     */
    private function isLegacyPipe($resource)
    {
        if (\PHP_VERSION_ID < 50428 || \PHP_VERSION_ID >= 50500 && \PHP_VERSION_ID < 50512) {
            $meta = \stream_get_meta_data($resource);
            if (isset($meta['stream_type']) && $meta['stream_type'] === 'STDIO') {
                return \true;
            }
        }
        return \false;
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Stream;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitterInterface;
/**
 * The `ReadableStreamInterface` is responsible for providing an interface for
 * read-only streams and the readable side of duplex streams.
 *
 * Besides defining a few methods, this interface also implements the
 * `EventEmitterInterface` which allows you to react to certain events:
 *
 * data event:
 *     The `data` event will be emitted whenever some data was read/received
 *     from this source stream.
 *     The event receives a single mixed argument for incoming data.
 *
 *     ```php
 *     $stream->on('data', function ($data) {
 *         echo $data;
 *     });
 *     ```
 *
 *     This event MAY be emitted any number of times, which may be zero times if
 *     this stream does not send any data at all.
 *     It SHOULD not be emitted after an `end` or `close` event.
 *
 *     The given `$data` argument may be of mixed type, but it's usually
 *     recommended it SHOULD be a `string` value or MAY use a type that allows
 *     representation as a `string` for maximum compatibility.
 *
 *     Many common streams (such as a TCP/IP connection or a file-based stream)
 *     will emit the raw (binary) payload data that is received over the wire as
 *     chunks of `string` values.
 *
 *     Due to the stream-based nature of this, the sender may send any number
 *     of chunks with varying sizes. There are no guarantees that these chunks
 *     will be received with the exact same framing the sender intended to send.
 *     In other words, many lower-level protocols (such as TCP/IP) transfer the
 *     data in chunks that may be anywhere between single-byte values to several
 *     dozens of kilobytes. You may want to apply a higher-level protocol to
 *     these low-level data chunks in order to achieve proper message framing.
 *
 * end event:
 *     The `end` event will be emitted once the source stream has successfully
 *     reached the end of the stream (EOF).
 *
 *     ```php
 *     $stream->on('end', function () {
 *         echo 'END';
 *     });
 *     ```
 *
 *     This event SHOULD be emitted once or never at all, depending on whether
 *     a successful end was detected.
 *     It SHOULD NOT be emitted after a previous `end` or `close` event.
 *     It MUST NOT be emitted if the stream closes due to a non-successful
 *     end, such as after a previous `error` event.
 *
 *     After the stream is ended, it MUST switch to non-readable mode,
 *     see also `isReadable()`.
 *
 *     This event will only be emitted if the *end* was reached successfully,
 *     not if the stream was interrupted by an unrecoverable error or explicitly
 *     closed. Not all streams know this concept of a "successful end".
 *     Many use-cases involve detecting when the stream closes (terminates)
 *     instead, in this case you should use the `close` event.
 *     After the stream emits an `end` event, it SHOULD usually be followed by a
 *     `close` event.
 *
 *     Many common streams (such as a TCP/IP connection or a file-based stream)
 *     will emit this event if either the remote side closes the connection or
 *     a file handle was successfully read until reaching its end (EOF).
 *
 *     Note that this event should not be confused with the `end()` method.
 *     This event defines a successful end *reading* from a source stream, while
 *     the `end()` method defines *writing* a successful end to a destination
 *     stream.
 *
 * error event:
 *     The `error` event will be emitted once a fatal error occurs, usually while
 *     trying to read from this stream.
 *     The event receives a single `Exception` argument for the error instance.
 *
 *     ```php
 *     $stream->on('error', function (Exception $e) {
 *         echo 'Error: ' . $e->getMessage() . PHP_EOL;
 *     });
 *     ```
 *
 *     This event SHOULD be emitted once the stream detects a fatal error, such
 *     as a fatal transmission error or after an unexpected `data` or premature
 *     `end` event.
 *     It SHOULD NOT be emitted after a previous `error`, `end` or `close` event.
 *     It MUST NOT be emitted if this is not a fatal error condition, such as
 *     a temporary network issue that did not cause any data to be lost.
 *
 *     After the stream errors, it MUST close the stream and SHOULD thus be
 *     followed by a `close` event and then switch to non-readable mode, see
 *     also `close()` and `isReadable()`.
 *
 *     Many common streams (such as a TCP/IP connection or a file-based stream)
 *     only deal with data transmission and do not make assumption about data
 *     boundaries (such as unexpected `data` or premature `end` events).
 *     In other words, many lower-level protocols (such as TCP/IP) may choose
 *     to only emit this for a fatal transmission error once and will then
 *     close (terminate) the stream in response.
 *
 *     If this stream is a `DuplexStreamInterface`, you should also notice
 *     how the writable side of the stream also implements an `error` event.
 *     In other words, an error may occur while either reading or writing the
 *     stream which should result in the same error processing.
 *
 * close event:
 *     The `close` event will be emitted once the stream closes (terminates).
 *
 *     ```php
 *     $stream->on('close', function () {
 *         echo 'CLOSED';
 *     });
 *     ```
 *
 *     This event SHOULD be emitted once or never at all, depending on whether
 *     the stream ever terminates.
 *     It SHOULD NOT be emitted after a previous `close` event.
 *
 *     After the stream is closed, it MUST switch to non-readable mode,
 *     see also `isReadable()`.
 *
 *     Unlike the `end` event, this event SHOULD be emitted whenever the stream
 *     closes, irrespective of whether this happens implicitly due to an
 *     unrecoverable error or explicitly when either side closes the stream.
 *     If you only want to detect a *successful* end, you should use the `end`
 *     event instead.
 *
 *     Many common streams (such as a TCP/IP connection or a file-based stream)
 *     will likely choose to emit this event after reading a *successful* `end`
 *     event or after a fatal transmission `error` event.
 *
 *     If this stream is a `DuplexStreamInterface`, you should also notice
 *     how the writable side of the stream also implements a `close` event.
 *     In other words, after receiving this event, the stream MUST switch into
 *     non-writable AND non-readable mode, see also `isWritable()`.
 *     Note that this event should not be confused with the `end` event.
 *
 * The event callback functions MUST be a valid `callable` that obeys strict
 * parameter definitions and MUST accept event parameters exactly as documented.
 * The event callback functions MUST NOT throw an `Exception`.
 * The return value of the event callback functions will be ignored and has no
 * effect, so for performance reasons you're recommended to not return any
 * excessive data structures.
 *
 * Every implementation of this interface MUST follow these event semantics in
 * order to be considered a well-behaving stream.
 *
 * > Note that higher-level implementations of this interface may choose to
 *   define additional events with dedicated semantics not defined as part of
 *   this low-level stream specification. Conformance with these event semantics
 *   is out of scope for this interface, so you may also have to refer to the
 *   documentation of such a higher-level implementation.
 *
 * @see EventEmitterInterface
 */
interface ReadableStreamInterface extends EventEmitterInterface
{
    /**
     * Checks whether this stream is in a readable state (not closed already).
     *
     * This method can be used to check if the stream still accepts incoming
     * data events or if it is ended or closed already.
     * Once the stream is non-readable, no further `data` or `end` events SHOULD
     * be emitted.
     *
     * ```php
     * assert($stream->isReadable() === false);
     *
     * $stream->on('data', assertNeverCalled());
     * $stream->on('end', assertNeverCalled());
     * ```
     *
     * A successfully opened stream always MUST start in readable mode.
     *
     * Once the stream ends or closes, it MUST switch to non-readable mode.
     * This can happen any time, explicitly through `close()` or
     * implicitly due to a remote close or an unrecoverable transmission error.
     * Once a stream has switched to non-readable mode, it MUST NOT transition
     * back to readable mode.
     *
     * If this stream is a `DuplexStreamInterface`, you should also notice
     * how the writable side of the stream also implements an `isWritable()`
     * method. Unless this is a half-open duplex stream, they SHOULD usually
     * have the same return value.
     *
     * @return bool
     */
    public function isReadable();
    /**
     * Pauses reading incoming data events.
     *
     * Removes the data source file descriptor from the event loop. This
     * allows you to throttle incoming data.
     *
     * Unless otherwise noted, a successfully opened stream SHOULD NOT start
     * in paused state.
     *
     * Once the stream is paused, no futher `data` or `end` events SHOULD
     * be emitted.
     *
     * ```php
     * $stream->pause();
     *
     * $stream->on('data', assertShouldNeverCalled());
     * $stream->on('end', assertShouldNeverCalled());
     * ```
     *
     * This method is advisory-only, though generally not recommended, the
     * stream MAY continue emitting `data` events.
     *
     * You can continue processing events by calling `resume()` again.
     *
     * Note that both methods can be called any number of times, in particular
     * calling `pause()` more than once SHOULD NOT have any effect.
     *
     * @see self::resume()
     * @return void
     */
    public function pause();
    /**
     * Resumes reading incoming data events.
     *
     * Re-attach the data source after a previous `pause()`.
     *
     * ```php
     * $stream->pause();
     *
     * Loop::addTimer(1.0, function () use ($stream) {
     *     $stream->resume();
     * });
     * ```
     *
     * Note that both methods can be called any number of times, in particular
     * calling `resume()` without a prior `pause()` SHOULD NOT have any effect.
     *
     * @see self::pause()
     * @return void
     */
    public function resume();
    /**
     * Pipes all the data from this readable source into the given writable destination.
     *
     * Automatically sends all incoming data to the destination.
     * Automatically throttles the source based on what the destination can handle.
     *
     * ```php
     * $source->pipe($dest);
     * ```
     *
     * Similarly, you can also pipe an instance implementing `DuplexStreamInterface`
     * into itself in order to write back all the data that is received.
     * This may be a useful feature for a TCP/IP echo service:
     *
     * ```php
     * $connection->pipe($connection);
     * ```
     *
     * This method returns the destination stream as-is, which can be used to
     * set up chains of piped streams:
     *
     * ```php
     * $source->pipe($decodeGzip)->pipe($filterBadWords)->pipe($dest);
     * ```
     *
     * By default, this will call `end()` on the destination stream once the
     * source stream emits an `end` event. This can be disabled like this:
     *
     * ```php
     * $source->pipe($dest, array('end' => false));
     * ```
     *
     * Note that this only applies to the `end` event.
     * If an `error` or explicit `close` event happens on the source stream,
     * you'll have to manually close the destination stream:
     *
     * ```php
     * $source->pipe($dest);
     * $source->on('close', function () use ($dest) {
     *     $dest->end('BYE!');
     * });
     * ```
     *
     * If the source stream is not readable (closed state), then this is a NO-OP.
     *
     * ```php
     * $source->close();
     * $source->pipe($dest); // NO-OP
     * ```
     *
     * If the destinantion stream is not writable (closed state), then this will simply
     * throttle (pause) the source stream:
     *
     * ```php
     * $dest->close();
     * $source->pipe($dest); // calls $source->pause()
     * ```
     *
     * Similarly, if the destination stream is closed while the pipe is still
     * active, it will also throttle (pause) the source stream:
     *
     * ```php
     * $source->pipe($dest);
     * $dest->close(); // calls $source->pause()
     * ```
     *
     * Once the pipe is set up successfully, the destination stream MUST emit
     * a `pipe` event with this source stream an event argument.
     *
     * @param WritableStreamInterface $dest
     * @param array $options
     * @return WritableStreamInterface $dest stream as-is
     */
    public function pipe(WritableStreamInterface $dest, array $options = array());
    /**
     * Closes the stream (forcefully).
     *
     * This method can be used to (forcefully) close the stream.
     *
     * ```php
     * $stream->close();
     * ```
     *
     * Once the stream is closed, it SHOULD emit a `close` event.
     * Note that this event SHOULD NOT be emitted more than once, in particular
     * if this method is called multiple times.
     *
     * After calling this method, the stream MUST switch into a non-readable
     * mode, see also `isReadable()`.
     * This means that no further `data` or `end` events SHOULD be emitted.
     *
     * ```php
     * $stream->close();
     * assert($stream->isReadable() === false);
     *
     * $stream->on('data', assertNeverCalled());
     * $stream->on('end', assertNeverCalled());
     * ```
     *
     * If this stream is a `DuplexStreamInterface`, you should also notice
     * how the writable side of the stream also implements a `close()` method.
     * In other words, after calling this method, the stream MUST switch into
     * non-writable AND non-readable mode, see also `isWritable()`.
     * Note that this method should not be confused with the `end()` method.
     *
     * @return void
     * @see WritableStreamInterface::close()
     */
    public function close();
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Stream;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use InvalidArgumentException;
/**
 * The `ThroughStream` implements the
 * [`DuplexStreamInterface`](#duplexstreaminterface) and will simply pass any data
 * you write to it through to its readable end.
 *
 * ```php
 * $through = new ThroughStream();
 * $through->on('data', $this->expectCallableOnceWith('hello'));
 *
 * $through->write('hello');
 * ```
 *
 * Similarly, the [`end()` method](#end) will end the stream and emit an
 * [`end` event](#end-event) and then [`close()`](#close-1) the stream.
 * The [`close()` method](#close-1) will close the stream and emit a
 * [`close` event](#close-event).
 * Accordingly, this is can also be used in a [`pipe()`](#pipe) context like this:
 *
 * ```php
 * $through = new ThroughStream();
 * $source->pipe($through)->pipe($dest);
 * ```
 *
 * Optionally, its constructor accepts any callable function which will then be
 * used to *filter* any data written to it. This function receives a single data
 * argument as passed to the writable side and must return the data as it will be
 * passed to its readable end:
 *
 * ```php
 * $through = new ThroughStream('strtoupper');
 * $source->pipe($through)->pipe($dest);
 * ```
 *
 * Note that this class makes no assumptions about any data types. This can be
 * used to convert data, for example for transforming any structured data into
 * a newline-delimited JSON (NDJSON) stream like this:
 *
 * ```php
 * $through = new ThroughStream(function ($data) {
 *     return json_encode($data) . PHP_EOL;
 * });
 * $through->on('data', $this->expectCallableOnceWith("[2, true]\n"));
 *
 * $through->write(array(2, true));
 * ```
 *
 * The callback function is allowed to throw an `Exception`. In this case,
 * the stream will emit an `error` event and then [`close()`](#close-1) the stream.
 *
 * ```php
 * $through = new ThroughStream(function ($data) {
 *     if (!is_string($data)) {
 *         throw new \UnexpectedValueException('Only strings allowed');
 *     }
 *     return $data;
 * });
 * $through->on('error', $this->expectCallableOnce()));
 * $through->on('close', $this->expectCallableOnce()));
 * $through->on('data', $this->expectCallableNever()));
 *
 * $through->write(2);
 * ```
 *
 * @see WritableStreamInterface::write()
 * @see WritableStreamInterface::end()
 * @see DuplexStreamInterface::close()
 * @see WritableStreamInterface::pipe()
 */
final class ThroughStream extends EventEmitter implements DuplexStreamInterface
{
    private $readable = \true;
    private $writable = \true;
    private $closed = \false;
    private $paused = \false;
    private $drain = \false;
    private $callback;
    public function __construct($callback = null)
    {
        if ($callback !== null && !\is_callable($callback)) {
            throw new InvalidArgumentException('Invalid transformation callback given');
        }
        $this->callback = $callback;
    }
    public function pause()
    {
        // only allow pause if still readable, false otherwise
        $this->paused = $this->readable;
    }
    public function resume()
    {
        $this->paused = \false;
        // emit drain event if previous write was paused (throttled)
        if ($this->drain) {
            $this->drain = \false;
            $this->emit('drain');
        }
    }
    public function pipe(WritableStreamInterface $dest, array $options = array())
    {
        return Util::pipe($this, $dest, $options);
    }
    public function isReadable()
    {
        return $this->readable;
    }
    public function isWritable()
    {
        return $this->writable;
    }
    public function write($data)
    {
        if (!$this->writable) {
            return \false;
        }
        if ($this->callback !== null) {
            try {
                $data = \call_user_func($this->callback, $data);
            } catch (\Exception $e) {
                $this->emit('error', array($e));
                $this->close();
                return \false;
            }
        }
        $this->emit('data', array($data));
        // emit drain event on next resume if currently paused (throttled)
        if ($this->paused) {
            $this->drain = \true;
        }
        // continue writing if still writable and not paused (throttled), false otherwise
        return $this->writable && !$this->paused;
    }
    public function end($data = null)
    {
        if (!$this->writable) {
            return;
        }
        if (null !== $data) {
            $this->write($data);
            // return if write() already caused the stream to close
            if (!$this->writable) {
                return;
            }
        }
        $this->readable = \false;
        $this->writable = \false;
        $this->paused = \false;
        $this->drain = \false;
        $this->emit('end');
        $this->close();
    }
    public function close()
    {
        if ($this->closed) {
            return;
        }
        $this->readable = \false;
        $this->writable = \false;
        $this->paused = \false;
        $this->drain = \false;
        $this->closed = \true;
        $this->callback = null;
        $this->emit('close');
        $this->removeAllListeners();
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Stream;

final class Util
{
    /**
     * Pipes all the data from the given $source into the $dest
     *
     * @param ReadableStreamInterface $source
     * @param WritableStreamInterface $dest
     * @param array $options
     * @return WritableStreamInterface $dest stream as-is
     * @see ReadableStreamInterface::pipe() for more details
     */
    public static function pipe(ReadableStreamInterface $source, WritableStreamInterface $dest, array $options = array())
    {
        // source not readable => NO-OP
        if (!$source->isReadable()) {
            return $dest;
        }
        // destination not writable => just pause() source
        if (!$dest->isWritable()) {
            $source->pause();
            return $dest;
        }
        $dest->emit('pipe', array($source));
        // forward all source data events as $dest->write()
        $source->on('data', $dataer = function ($data) use ($source, $dest) {
            $feedMore = $dest->write($data);
            if (\false === $feedMore) {
                $source->pause();
            }
        });
        $dest->on('close', function () use ($source, $dataer) {
            $source->removeListener('data', $dataer);
            $source->pause();
        });
        // forward destination drain as $source->resume()
        $dest->on('drain', $drainer = function () use ($source) {
            $source->resume();
        });
        $source->on('close', function () use ($dest, $drainer) {
            $dest->removeListener('drain', $drainer);
        });
        // forward end event from source as $dest->end()
        $end = isset($options['end']) ? $options['end'] : \true;
        if ($end) {
            $source->on('end', $ender = function () use ($dest) {
                $dest->end();
            });
            $dest->on('close', function () use ($source, $ender) {
                $source->removeListener('end', $ender);
            });
        }
        return $dest;
    }
    public static function forwardEvents($source, $target, array $events)
    {
        foreach ($events as $event) {
            $source->on($event, function () use ($event, $target) {
                $target->emit($event, \func_get_args());
            });
        }
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Stream;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitter;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\Loop;
use NightwatchAgent_kden27khxA4QoEfj\React\EventLoop\LoopInterface;
final class WritableResourceStream extends EventEmitter implements WritableStreamInterface
{
    private $stream;
    /** @var LoopInterface */
    private $loop;
    /**
     * @var int
     */
    private $softLimit;
    /**
     * @var int
     */
    private $writeChunkSize;
    private $listening = \false;
    private $writable = \true;
    private $closed = \false;
    private $data = '';
    /**
     * @param resource $stream
     * @param ?LoopInterface $loop
     * @param ?int $writeBufferSoftLimit
     * @param ?int $writeChunkSize
     */
    public function __construct($stream, $loop = null, $writeBufferSoftLimit = null, $writeChunkSize = null)
    {
        if (!\is_resource($stream) || \get_resource_type($stream) !== "stream") {
            throw new \InvalidArgumentException('First parameter must be a valid stream resource');
        }
        // ensure resource is opened for writing (fopen mode must contain either of "waxc+")
        $meta = \stream_get_meta_data($stream);
        if (isset($meta['mode']) && $meta['mode'] !== '' && \strtr($meta['mode'], 'waxc+', '.....') === $meta['mode']) {
            throw new \InvalidArgumentException('Given stream resource is not opened in write mode');
        }
        // this class relies on non-blocking I/O in order to not interrupt the event loop
        // e.g. pipes on Windows do not support this: https://bugs.php.net/bug.php?id=47918
        if (\stream_set_blocking($stream, \false) !== \true) {
            throw new \RuntimeException('Unable to set stream resource to non-blocking mode');
        }
        if ($loop !== null && !$loop instanceof LoopInterface) {
            // manual type check to support legacy PHP < 7.1
            throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
        }
        $this->stream = $stream;
        $this->loop = $loop ?: Loop::get();
        $this->softLimit = $writeBufferSoftLimit === null ? 65536 : (int) $writeBufferSoftLimit;
        $this->writeChunkSize = $writeChunkSize === null ? -1 : (int) $writeChunkSize;
    }
    public function isWritable()
    {
        return $this->writable;
    }
    public function write($data)
    {
        if (!$this->writable) {
            return \false;
        }
        $this->data .= $data;
        if (!$this->listening && $this->data !== '') {
            $this->listening = \true;
            $this->loop->addWriteStream($this->stream, array($this, 'handleWrite'));
        }
        return !isset($this->data[$this->softLimit - 1]);
    }
    public function end($data = null)
    {
        if (null !== $data) {
            $this->write($data);
        }
        $this->writable = \false;
        // close immediately if buffer is already empty
        // otherwise wait for buffer to flush first
        if ($this->data === '') {
            $this->close();
        }
    }
    public function close()
    {
        if ($this->closed) {
            return;
        }
        if ($this->listening) {
            $this->listening = \false;
            $this->loop->removeWriteStream($this->stream);
        }
        $this->closed = \true;
        $this->writable = \false;
        $this->data = '';
        $this->emit('close');
        $this->removeAllListeners();
        if (\is_resource($this->stream)) {
            \fclose($this->stream);
        }
    }
    /** @internal */
    public function handleWrite()
    {
        $error = null;
        \set_error_handler(function ($_, $errstr) use (&$error) {
            $error = $errstr;
        });
        if ($this->writeChunkSize === -1) {
            $sent = \fwrite($this->stream, $this->data);
        } else {
            $sent = \fwrite($this->stream, $this->data, $this->writeChunkSize);
        }
        \restore_error_handler();
        // Only report errors if *nothing* could be sent and an error has been raised.
        // Ignore non-fatal warnings if *some* data could be sent.
        // Any hard (permanent) error will fail to send any data at all.
        // Sending excessive amounts of data will only flush *some* data and then
        // report a temporary error (EAGAIN) which we do not raise here in order
        // to keep the stream open for further tries to write.
        // Should this turn out to be a permanent error later, it will eventually
        // send *nothing* and we can detect this.
        if (($sent === 0 || $sent === \false) && $error !== null) {
            $this->emit('error', array(new \RuntimeException('Unable to write to stream: ' . $error)));
            $this->close();
            return;
        }
        $exceeded = isset($this->data[$this->softLimit - 1]);
        $this->data = (string) \substr($this->data, $sent);
        // buffer has been above limit and is now below limit
        if ($exceeded && !isset($this->data[$this->softLimit - 1])) {
            $this->emit('drain');
        }
        // buffer is now completely empty => stop trying to write
        if ($this->data === '') {
            // stop waiting for resource to be writable
            if ($this->listening) {
                $this->loop->removeWriteStream($this->stream);
                $this->listening = \false;
            }
            // buffer is end()ing and now completely empty => close buffer
            if (!$this->writable) {
                $this->close();
            }
        }
    }
}
<?php

namespace NightwatchAgent_kden27khxA4QoEfj\React\Stream;

use NightwatchAgent_kden27khxA4QoEfj\Evenement\EventEmitterInterface;
/**
 * The `WritableStreamInterface` is responsible for providing an interface for
 * write-only streams and the writable side of duplex streams.
 *
 * Besides defining a few methods, this interface also implements the
 * `EventEmitterInterface` which allows you to react to certain events:
 *
 * drain event:
 *     The `drain` event will be emitted whenever the write buffer became full
 *     previously and is now ready to accept more data.
 *
 *     ```php
 *     $stream->on('drain', function () use ($stream) {
 *         echo 'Stream is now ready to accept more data';
 *     });
 *     ```
 *
 *     This event SHOULD be emitted once every time the buffer became full
 *     previously and is now ready to accept more data.
 *     In other words, this event MAY be emitted any number of times, which may
 *     be zero times if the buffer never became full in the first place.
 *     This event SHOULD NOT be emitted if the buffer has not become full
 *     previously.
 *
 *     This event is mostly used internally, see also `write()` for more details.
 *
 * pipe event:
 *     The `pipe` event will be emitted whenever a readable stream is `pipe()`d
 *     into this stream.
 *     The event receives a single `ReadableStreamInterface` argument for the
 *     source stream.
 *
 *     ```php
 *     $stream->on('pipe', function (ReadableStreamInterface $source) use ($stream) {
 *         echo 'Now receiving piped data';
 *
 *         // explicitly close target if source emits an error
 *         $source->on('error', function () use ($stream) {
 *             $stream->close();
 *         });
 *     });
 *
 *     $source->pipe($stream);
 *     ```
 *
 *     This event MUST be emitted once for each readable stream that is
 *     successfully piped into this destination stream.
 *     In other words, this event MAY be emitted any number of times, which may
 *     be zero times if no stream is ever piped into this stream.
 *     This event MUST NOT be emitted if either the source is not readable
 *     (closed already) or this destination is not writable (closed already).
 *
 *     This event is mostly used internally, see also `pipe()` for more details.
 *
 * error event:
 *     The `error` event will be emitted once a fatal error occurs, usually while
 *     trying to write to this stream.
 *     The event receives a single `Exception` argument for the error instance.
 *
 *     ```php
 *     $stream->on('error', function (Exception $e) {
 *         echo 'Error: ' . $e->getMessage() . PHP_EOL;
 *     });
 *     ```
 *
 *     This event SHOULD be emitted once the stream detects a fatal error, such
 *     as a fatal transmission error.
 *     It SHOULD NOT be emitted after a previous `error` or `close` event.
 *     It MUST NOT be emitted if this is not a fatal error condition, such as
 *     a temporary network issue that did not cause any data to be lost.
 *
 *     After the stream errors, it MUST close the stream and SHOULD thus be
 *     followed by a `close` event and then switch to non-writable mode, see
 *     also `close()` and `isWritable()`.
 *
 *     Many common streams (such as a TCP/IP connection or a file-based stream)
 *     only deal with data transmission and may choose
 *     to only emit this for a fatal transmission error once and will then
 *     close (terminate) the stream in response.
 *
 *     If this stream is a `DuplexStreamInterface`, you should also notice
 *     how the readable side of the stream also implements an `error` event.
 *     In other words, an error may occur while either reading or writing the
 *     stream which should result in the same error processing.
 *
 * close event:
 *     The `close` event will be emitted once the stream closes (terminates).
 *
 *     ```php
 *     $stream->on('close', function () {
 *         echo 'CLOSED';
 *     });
 *     ```
 *
 *     This event SHOULD be emitted once or never at all, depending on whether
 *     the stream ever terminates.
 *     It SHOULD NOT be emitted after a previous `close` event.
 *
 *     After the stream is closed, it MUST switch to non-writable mode,
 *     see also `isWritable()`.
 *
 *     This event SHOULD be emitted whenever the stream closes, irrespective of
 *     whether this happens implicitly due to an unrecoverable error or
 *     explicitly when either side closes the stream.
 *
 *     Many common streams (such as a TCP/IP connection or a file-based stream)
 *     will likely choose to emit this event after flushing the buffer from
 *     the `end()` method, after receiving a *successful* `end` event or after
 *     a fatal transmission `error` event.
 *
 *     If this stream is a `DuplexStreamInterface`, you should also notice
 *     how the readable side of the stream also implements a `close` event.
 *     In other words, after receiving this event, the stream MUST switch into
 *     non-writable AND non-readable mode, see also `isReadable()`.
 *     Note that this event should not be confused with the `end` event.
 *
 * The event callback functions MUST be a valid `callable` that obeys strict
 * parameter definitions and MUST accept event parameters exactly as documented.
 * The event callback functions MUST NOT throw an `Exception`.
 * The return value of the event callback functions will be ignored and has no
 * effect, so for performance reasons you're recommended to not return any
 * excessive data structures.
 *
 * Every implementation of this interface MUST follow these event semantics in
 * order to be considered a well-behaving stream.
 *
 * > Note that higher-level implementations of this interface may choose to
 *   define additional events with dedicated semantics not defined as part of
 *   this low-level stream specification. Conformance with these event semantics
 *   is out of scope for this interface, so you may also have to refer to the
 *   documentation of such a higher-level implementation.
 *
 * @see EventEmitterInterface
 * @see DuplexStreamInterface
 */
interface WritableStreamInterface extends EventEmitterInterface
{
    /**
     * Checks whether this stream is in a writable state (not closed already).
     *
     * This method can be used to check if the stream still accepts writing
     * any data or if it is ended or closed already.
     * Writing any data to a non-writable stream is a NO-OP:
     *
     * ```php
     * assert($stream->isWritable() === false);
     *
     * $stream->write('end'); // NO-OP
     * $stream->end('end'); // NO-OP
     * ```
     *
     * A successfully opened stream always MUST start in writable mode.
     *
     * Once the stream ends or closes, it MUST switch to non-writable mode.
     * This can happen any time, explicitly through `end()` or `close()` or
     * implicitly due to a remote close or an unrecoverable transmission error.
     * Once a stream has switched to non-writable mode, it MUST NOT transition
     * back to writable mode.
     *
     * If this stream is a `DuplexStreamInterface`, you should also notice
     * how the readable side of the stream also implements an `isReadable()`
     * method. Unless this is a half-open duplex stream, they SHOULD usually
     * have the same return value.
     *
     * @return bool
     */
    public function isWritable();
    /**
     * Write some data into the stream.
     *
     * A successful write MUST be confirmed with a boolean `true`, which means
     * that either the data was written (flushed) immediately or is buffered and
     * scheduled for a future write. Note that this interface gives you no
     * control over explicitly flushing the buffered data, as finding the
     * appropriate time for this is beyond the scope of this interface and left
     * up to the implementation of this interface.
     *
     * Many common streams (such as a TCP/IP connection or file-based stream)
     * may choose to buffer all given data and schedule a future flush by using
     * an underlying EventLoop to check when the resource is actually writable.
     *
     * If a stream cannot handle writing (or flushing) the data, it SHOULD emit
     * an `error` event and MAY `close()` the stream if it can not recover from
     * this error.
     *
     * If the internal buffer is full after adding `$data`, then `write()`
     * SHOULD return `false`, indicating that the caller should stop sending
     * data until the buffer drains.
     * The stream SHOULD send a `drain` event once the buffer is ready to accept
     * more data.
     *
     * Similarly, if the stream is not writable (already in a closed state)
     * it MUST NOT process the given `$data` and SHOULD return `false`,
     * indicating that the caller should stop sending data.
     *
     * The given `$data` argument MAY be of mixed type, but it's usually
     * recommended it SHOULD be a `string` value or MAY use a type that allows
     * representation as a `string` for maximum compatibility.
     *
     * Many common streams (such as a TCP/IP connection or a file-based stream)
     * will only accept the raw (binary) payload data that is transferred over
     * the wire as chunks of `string` values.
     *
     * Due to the stream-based nature of this, the sender may send any number
     * of chunks with varying sizes. There are no guarantees that these chunks
     * will be received with the exact same framing the sender intended to send.
     * In other words, many lower-level protocols (such as TCP/IP) transfer the
     * data in chunks that may be anywhere between single-byte values to several
     * dozens of kilobytes. You may want to apply a higher-level protocol to
     * these low-level data chunks in order to achieve proper message framing.
     *
     * @param mixed|string $data
     * @return bool
     */
    public function write($data);
    /**
     * Successfully ends the stream (after optionally sending some final data).
     *
     * This method can be used to successfully end the stream, i.e. close
     * the stream after sending out all data that is currently buffered.
     *
     * ```php
     * $stream->write('hello');
     * $stream->write('world');
     * $stream->end();
     * ```
     *
     * If there's no data currently buffered and nothing to be flushed, then
     * this method MAY `close()` the stream immediately.
     *
     * If there's still data in the buffer that needs to be flushed first, then
     * this method SHOULD try to write out this data and only then `close()`
     * the stream.
     * Once the stream is closed, it SHOULD emit a `close` event.
     *
     * Note that this interface gives you no control over explicitly flushing
     * the buffered data, as finding the appropriate time for this is beyond the
     * scope of this interface and left up to the implementation of this
     * interface.
     *
     * Many common streams (such as a TCP/IP connection or file-based stream)
     * may choose to buffer all given data and schedule a future flush by using
     * an underlying EventLoop to check when the resource is actually writable.
     *
     * You can optionally pass some final data that is written to the stream
     * before ending the stream. If a non-`null` value is given as `$data`, then
     * this method will behave just like calling `write($data)` before ending
     * with no data.
     *
     * ```php
     * // shorter version
     * $stream->end('bye');
     *
     * // same as longer version
     * $stream->write('bye');
     * $stream->end();
     * ```
     *
     * After calling this method, the stream MUST switch into a non-writable
     * mode, see also `isWritable()`.
     * This means that no further writes are possible, so any additional
     * `write()` or `end()` calls have no effect.
     *
     * ```php
     * $stream->end();
     * assert($stream->isWritable() === false);
     *
     * $stream->write('nope'); // NO-OP
     * $stream->end(); // NO-OP
     * ```
     *
     * If this stream is a `DuplexStreamInterface`, calling this method SHOULD
     * also end its readable side, unless the stream supports half-open mode.
     * In other words, after calling this method, these streams SHOULD switch
     * into non-writable AND non-readable mode, see also `isReadable()`.
     * This implies that in this case, the stream SHOULD NOT emit any `data`
     * or `end` events anymore.
     * Streams MAY choose to use the `pause()` method logic for this, but
     * special care may have to be taken to ensure a following call to the
     * `resume()` method SHOULD NOT continue emitting readable events.
     *
     * Note that this method should not be confused with the `close()` method.
     *
     * @param mixed|string|null $data
     * @return void
     */
    public function end($data = null);
    /**
     * Closes the stream (forcefully).
     *
     * This method can be used to forcefully close the stream, i.e. close
     * the stream without waiting for any buffered data to be flushed.
     * If there's still data in the buffer, this data SHOULD be discarded.
     *
     * ```php
     * $stream->close();
     * ```
     *
     * Once the stream is closed, it SHOULD emit a `close` event.
     * Note that this event SHOULD NOT be emitted more than once, in particular
     * if this method is called multiple times.
     *
     * After calling this method, the stream MUST switch into a non-writable
     * mode, see also `isWritable()`.
     * This means that no further writes are possible, so any additional
     * `write()` or `end()` calls have no effect.
     *
     * ```php
     * $stream->close();
     * assert($stream->isWritable() === false);
     *
     * $stream->write('nope'); // NO-OP
     * $stream->end(); // NO-OP
     * ```
     *
     * Note that this method should not be confused with the `end()` method.
     * Unlike the `end()` method, this method does not take care of any existing
     * buffers and simply discards any buffer contents.
     * Likewise, this method may also be called after calling `end()` on a
     * stream in order to stop waiting for the stream to flush its final data.
     *
     * ```php
     * $stream->end();
     * Loop::addTimer(1.0, function () use ($stream) {
     *     $stream->close();
     * });
     * ```
     *
     * If this stream is a `DuplexStreamInterface`, you should also notice
     * how the readable side of the stream also implements a `close()` method.
     * In other words, after calling this method, the stream MUST switch into
     * non-writable AND non-readable mode, see also `isReadable()`.
     *
     * @return void
     * @see ReadableStreamInterface::close()
     */
    public function close();
}
Jऑ2rs;95&jw]t`(!s ر    GBMB