示例#1
0
 /**
  * {@inheritdoc}
  */
 public function create(string $host, int $port = null, array $options = []) : Server
 {
     $protocol = (string) ($options['protocol'] ?? (null === $port ? 'unix' : 'tcp'));
     $autoClose = (bool) ($options['auto_close'] ?? true);
     $queue = (int) ($options['backlog'] ?? (defined('SOMAXCONN') ? SOMAXCONN : self::DEFAULT_BACKLOG));
     $pem = (string) ($options['pem'] ?? '');
     $passphrase = $options['passphrase'] ?? '';
     $name = (string) ($options['name'] ?? '');
     $verify = (string) ($options['verify_peer'] ?? self::DEFAULT_VERIFY_PEER);
     $allowSelfSigned = (bool) ($options['allow_self_signed'] ?? self::DEFAULT_ALLOW_SELF_SIGNED);
     $verifyDepth = (int) ($options['verify_depth'] ?? self::DEFAULT_VERIFY_DEPTH);
     $context = [];
     $context['socket'] = ['bindto' => Socket\makeName($host, $port), 'backlog' => $queue, 'ipv6_v6only' => true, 'so_reuseaddr' => (bool) ($options['reuseaddr'] ?? false), 'so_reuseport' => (bool) ($options['reuseport'] ?? false)];
     if ('' !== $pem) {
         if (!file_exists($pem)) {
             throw new InvalidArgumentError('No file found at given PEM path.');
         }
         $context['ssl'] = ['verify_peer' => $verify, 'verify_peer_name' => $verify, 'allow_self_signed' => $allowSelfSigned, 'verify_depth' => $verifyDepth, 'local_cert' => $pem, 'disable_compression' => true, 'SNI_enabled' => true, 'SNI_server_name' => $name, 'peer_name' => $name];
         if ('' !== $passphrase) {
             $context['ssl']['passphrase'] = $passphrase;
         }
     }
     $context = stream_context_create($context);
     $uri = Socket\makeUri($protocol, $host, $port);
     // Error reporting suppressed since stream_socket_server() emits an E_WARNING on failure (checked below).
     $socket = @stream_socket_server($uri, $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $context);
     if (!$socket || $errno) {
         throw new FailureException(sprintf('Could not create server %s: Errno: %d; %s', $uri, $errno, $errstr));
     }
     return new BasicServer($socket, $autoClose);
 }
 /**
  * {@inheritdoc}
  */
 public function create(string $host, int $port = null, array $options = []) : Datagram
 {
     $autoClose = (bool) ($options['auto_close'] ?? true);
     $context = [];
     $context['socket'] = [];
     $context['socket']['bindto'] = Socket\makeName($host, $port);
     $context = stream_context_create($context);
     $uri = Socket\makeUri('udp', $host, $port);
     // Error reporting suppressed since stream_socket_server() emits an E_WARNING on failure (checked below).
     $socket = @stream_socket_server($uri, $errno, $errstr, STREAM_SERVER_BIND, $context);
     if (!$socket || $errno) {
         throw new FailureException(sprintf('Could not create datagram on %s: Errno: %d; %s', $uri, $errno, $errstr));
     }
     return new BasicDatagram($socket, $autoClose);
 }
示例#3
0
 /**
  * {@inheritdoc}
  */
 public function connect(string $ip, int $port = null, array $options = []) : \Generator
 {
     $protocol = (string) ($options['protocol'] ?? (null === $port ? 'unix' : 'tcp'));
     $autoClose = (bool) ($options['auto_close'] ?? true);
     $allowSelfSigned = (bool) ($options['allow_self_signed'] ?? self::DEFAULT_ALLOW_SELF_SIGNED);
     $timeout = (double) ($options['timeout'] ?? self::DEFAULT_CONNECT_TIMEOUT);
     $verifyDepth = (int) ($options['verify_depth'] ?? self::DEFAULT_VERIFY_DEPTH);
     $cafile = (string) ($options['cafile'] ?? '');
     $name = (string) ($options['name'] ?? '');
     $cn = (string) ($options['cn'] ?? $name);
     $context = [];
     $context['socket'] = ['connect' => Socket\makeName($ip, $port)];
     $context['ssl'] = ['capture_peer_cert' => true, 'capture_peer_chain' => true, 'capture_peer_cert_chain' => true, 'verify_peer' => true, 'verify_peer_name' => true, 'allow_self_signed' => $allowSelfSigned, 'verify_depth' => $verifyDepth, 'CN_match' => $cn, 'SNI_enabled' => true, 'SNI_server_name' => $name, 'peer_name' => $name, 'disable_compression' => true, 'honor_cipher_order' => true];
     if ('' !== $cafile) {
         if (!file_exists($cafile)) {
             throw new InvalidArgumentError('No file exists at path given for cafile.');
         }
         $context['ssl']['cafile'] = $cafile;
     }
     $context = stream_context_create($context);
     $uri = Socket\makeUri($protocol, $ip, $port);
     // Error reporting suppressed since stream_socket_client() emits an E_WARNING on failure (checked below).
     $socket = @stream_socket_client($uri, $errno, $errstr, null, STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT, $context);
     if (!$socket || $errno) {
         throw new FailureException(sprintf('Could not connect to %s; Errno: %d; %s', $uri, $errno, $errstr));
     }
     $delayed = new Delayed();
     $await = Loop\await($socket, function ($resource, bool $expired, Io $await) use($delayed, $autoClose) {
         $await->free();
         if ($expired) {
             $delayed->reject(new TimeoutException('Connection attempt timed out.'));
             return;
         }
         $delayed->resolve(new NetworkSocket($resource, $autoClose));
     });
     $await->listen($timeout);
     try {
         return (yield $delayed);
     } finally {
         $await->free();
     }
 }
示例#4
0
 /**
  * {@inheritdoc}
  */
 public function send(string $address, int $port, string $data) : \Generator
 {
     if (!$this->isOpen()) {
         throw new UnavailableException('The datagram is no longer writable.');
     }
     $data = (string) $data;
     $length = strlen($data);
     $written = 0;
     $peer = Socket\makeName($address, $port);
     if ($this->writeQueue->isEmpty()) {
         if (0 === $length) {
             return $written;
         }
         $written = stream_socket_sendto($this->getResource(), substr($data, 0, self::MAX_PACKET_SIZE), 0, $peer);
         // Having difficulty finding a test to cover this scenario, but the check seems appropriate.
         if (false === $written || -1 === $written) {
             $message = 'Failed to write to datagram.';
             if ($error = error_get_last()) {
                 $message .= sprintf(' Errno: %d; %s', $error['type'], $error['message']);
             }
             throw new FailureException($message);
         }
         if ($length <= $written) {
             return $written;
         }
         $data = substr($data, $written);
     }
     if (null === $this->await) {
         $this->await = $this->createAwait($this->getResource(), $this->writeQueue);
         $this->await->listen();
     } elseif (!$this->await->isPending()) {
         $this->await->listen();
     }
     $delayed = new Delayed($this->onSendCancelled);
     $this->writeQueue->push([$data, $written, $peer, $delayed]);
     try {
         return (yield $delayed);
     } catch (Throwable $exception) {
         $this->free($exception);
         throw $exception;
     }
 }