/** * {@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); }
/** * {@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(); } }