HappyEyeBallsConnector.php 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. <?php
  2. namespace React\Socket;
  3. use React\Dns\Resolver\ResolverInterface;
  4. use React\EventLoop\Loop;
  5. use React\EventLoop\LoopInterface;
  6. use React\Promise;
  7. final class HappyEyeBallsConnector implements ConnectorInterface
  8. {
  9. private $loop;
  10. private $connector;
  11. private $resolver;
  12. public function __construct(LoopInterface $loop = null, ConnectorInterface $connector = null, ResolverInterface $resolver = null)
  13. {
  14. // $connector and $resolver arguments are actually required, marked
  15. // optional for technical reasons only. Nullable $loop without default
  16. // requires PHP 7.1, null default is also supported in legacy PHP
  17. // versions, but required parameters are not allowed after arguments
  18. // with null default. Mark all parameters optional and check accordingly.
  19. if ($connector === null || $resolver === null) {
  20. throw new \InvalidArgumentException('Missing required $connector or $resolver argument');
  21. }
  22. $this->loop = $loop ?: Loop::get();
  23. $this->connector = $connector;
  24. $this->resolver = $resolver;
  25. }
  26. public function connect($uri)
  27. {
  28. $original = $uri;
  29. if (\strpos($uri, '://') === false) {
  30. $uri = 'tcp://' . $uri;
  31. $parts = \parse_url($uri);
  32. if (isset($parts['scheme'])) {
  33. unset($parts['scheme']);
  34. }
  35. } else {
  36. $parts = \parse_url($uri);
  37. }
  38. if (!$parts || !isset($parts['host'])) {
  39. return Promise\reject(new \InvalidArgumentException(
  40. 'Given URI "' . $original . '" is invalid (EINVAL)',
  41. \defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : (\defined('PCNTL_EINVAL') ? \PCNTL_EINVAL : 22)
  42. ));
  43. }
  44. $host = \trim($parts['host'], '[]');
  45. // skip DNS lookup / URI manipulation if this URI already contains an IP
  46. if (@\inet_pton($host) !== false) {
  47. return $this->connector->connect($original);
  48. }
  49. $builder = new HappyEyeBallsConnectionBuilder(
  50. $this->loop,
  51. $this->connector,
  52. $this->resolver,
  53. $uri,
  54. $host,
  55. $parts
  56. );
  57. return $builder->connect();
  58. }
  59. }