Пример #1
0
 public function __construct($source, $destination, bool $closeSource = true, int $length = null, int $chunkSize = 4096, callable $transform = null)
 {
     $this->transform = $transform;
     if ($source instanceof ReadableStream) {
         $channel = $source->channel($chunkSize, $length);
     } elseif (!\is_resource($source)) {
         throw new \InvalidArgumentException(\sprintf('Expecting streamable source, given %s', \is_object($source) ? \get_class($source) : \gettype($source)));
     } else {
         $channel = $this->createSocketChannel($source, $chunkSize, $length);
     }
     if ($destination instanceof WritableStream) {
         $writer = $this->streamWriter($destination, $channel, $transform);
     } elseif (!\is_resource($destination)) {
         $channel->close();
         throw new \InvalidArgumentException(\sprintf('Expecting streamable destination, given %s', \is_object($destination) ? \get_class($destination) : \gettype($destination)));
     } else {
         $writer = $this->socketWriter($destination, $channel, $transform);
     }
     $this->copy = new Coroutine($writer);
     if ($closeSource) {
         $this->copy->when(function () use($source) {
             if (\is_resource($source)) {
                 Socket::shutdown($source);
             } else {
                 $source->close();
             }
         });
     }
     $this->resolve($this->copy);
 }
Пример #2
0
 protected function connectToAddress(string $address, float $timeout, bool $encrypt)
 {
     $url = \sprintf('%s://%s', $this->protocol, $address);
     $errno = null;
     $errstr = null;
     $context = \stream_context_create(\array_replace_recursive($this->options, ['socket' => ['connect' => $address]]));
     $socket = @\stream_socket_client($url, $errno, $errstr, $timeout ?: null, \STREAM_CLIENT_CONNECT | \STREAM_CLIENT_ASYNC_CONNECT, $context);
     if (!\is_resource($socket)) {
         throw new SocketException(\sprintf('Could not connect to "%s" (%s): [%s] %s', $url, $this->peer, $errno, \trim($errstr)));
     }
     try {
         \stream_set_blocking($socket, false);
         \stream_set_read_buffer($socket, 0);
         \stream_set_write_buffer($socket, 0);
         if ($this->tcpNoDelay) {
             Socket::setTcpNoDelay($socket, true);
         }
         if ($encrypt) {
             yield from $this->encryptSocketClient($socket, $timeout);
         } else {
             (yield new AwaitWrite($socket, $timeout));
         }
         return $socket;
     } catch (\Throwable $e) {
         Socket::shutdown($socket);
         throw $e;
     }
 }
Пример #3
0
 /**
  * {@inheritdoc}
  */
 public function close()
 {
     if ($this->socket !== null) {
         try {
             $this->reader->dispose();
             Socket::shutdown($this->socket);
         } finally {
             $this->socket = null;
         }
     }
 }
Пример #4
0
 protected function runServer($socket, callable $server) : \Generator
 {
     try {
         $result = $server($socket);
         if ($result instanceof \Generator) {
             $result = (yield from $result);
         }
         return $result;
     } finally {
         Socket::shutdown($socket);
     }
 }
Пример #5
0
 protected function socketReader($socket) : \Generator
 {
     $reader = new SocketReader($socket);
     $remaining = $this->length ?? \PHP_INT_MAX;
     $contents = '';
     try {
         while ($remaining && null !== ($chunk = (yield $reader->read($remaining)))) {
             $contents .= $chunk;
             $remaining -= \strlen($chunk);
         }
     } finally {
         $reader->dispose();
         if ($this->closeSource) {
             Socket::shutdown($socket);
         }
     }
     return $contents;
 }
Пример #6
0
 /**
  * {@inheritdoc}
  */
 public function close() : Awaitable
 {
     if ($this->socket !== null) {
         $this->disposeWriter();
         $this->disposeReader();
         try {
             Socket::shutdown($this->socket);
         } finally {
             $this->socket = null;
         }
     }
     return new Success($this->readBuffer);
 }