예제 #1
0
 public function get($key)
 {
     if (!isset($this->data[$key])) {
         return When::reject();
     }
     return When::resolve($this->data[$key]);
 }
예제 #2
0
 public function loadEtcResolvConf($filename)
 {
     if (!file_exists($filename)) {
         return When::reject(new \InvalidArgumentException("The filename for /etc/resolv.conf given does not exist: {$filename}"));
     }
     try {
         $deferred = new Deferred();
         $fd = fopen($filename, 'r');
         stream_set_blocking($fd, 0);
         $contents = '';
         $stream = new Stream($fd, $this->loop);
         $stream->on('data', function ($data) use(&$contents) {
             $contents .= $data;
         });
         $stream->on('end', function () use(&$contents, $deferred) {
             $deferred->resolve($contents);
         });
         $stream->on('error', function ($error) use($deferred) {
             $deferred->reject($error);
         });
         return $deferred->promise();
     } catch (\Exception $e) {
         return When::reject($e);
     }
 }
예제 #3
0
 public function checkConnectedSocket($socket)
 {
     // The following hack looks like the only way to
     // detect connection refused errors with PHP's stream sockets.
     if (false === stream_socket_get_name($socket, true)) {
         return When::reject(new ConnectionException('Connection refused'));
     }
     return When::resolve($socket);
 }
예제 #4
0
 public function createSocketForAddress($address, $port)
 {
     $url = $this->getSocketUrl($address, $port);
     $socket = stream_socket_client($url, $errno, $errstr, 0, STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT, $this->createStreamContext());
     if (!$socket) {
         return When::reject(new \RuntimeException(sprintf("connection to %s:%d failed: %s", $address, $port, $errstr), $errno));
     }
     stream_set_blocking($socket, 0);
     // wait for connection
     return $this->waitForStreamOnce($socket)->then(array($this, 'checkConnectedSocket'))->then(array($this, 'handleConnectedSocket'));
 }
예제 #5
0
 public function lookup(Query $query)
 {
     $id = $this->serializeQueryToIdentity($query);
     $expiredAt = $this->expiredAt;
     return $this->cache->get($id)->then(function ($value) use($query, $expiredAt) {
         $recordBag = unserialize($value);
         if (null !== $expiredAt && $expiredAt <= $query->currentTime) {
             return When::reject();
         }
         return $recordBag->all();
     });
 }
예제 #6
0
 /**
  * @covers React\Dns\Query\RetryExecutor
  * @test
  */
 public function queryShouldForwardNonTimeoutErrors()
 {
     $executor = $this->createExecutorMock();
     $executor->expects($this->once())->method('query')->with('8.8.8.8', $this->isInstanceOf('React\\Dns\\Query\\Query'))->will($this->returnCallback(function ($domain, $query) {
         return When::reject(new \Exception());
     }));
     $callback = $this->expectCallableNever();
     $errorback = $this->createCallableMock();
     $errorback->expects($this->once())->method('__invoke')->with($this->isInstanceOf('Exception'));
     $retryExecutor = new RetryExecutor($executor, 2);
     $query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
     $retryExecutor->query('8.8.8.8', $query)->then($callback, $errorback);
 }
예제 #7
0
 public function setAuth($auth)
 {
     if (!is_callable($auth)) {
         throw new InvalidArgumentException('Given authenticator is not a valid callable');
     }
     if ($this->protocolVersion !== null && $this->protocolVersion !== '5') {
         throw new UnexpectedValueException('Authentication requires SOCKS5. Consider using protocol version 5 or waive authentication');
     }
     // wrap authentication callback in order to cast its return value to a promise
     $this->auth = function ($username, $password) use($auth) {
         $ret = call_user_func($auth, $username, $password);
         if ($ret instanceof PromiseInterface) {
             return $ret;
         }
         return $ret ? When::resolve() : When::reject();
     };
 }
 /**
  * @covers React\Dns\Query\CachedExecutor
  * @test
  */
 public function callingQueryTwiceShouldUseCachedResult()
 {
     $cachedRecords = array(new Record('igor.io', Message::TYPE_A, Message::CLASS_IN));
     $executor = $this->createExecutorMock();
     $executor->expects($this->once())->method('query')->will($this->callQueryCallbackWithAddress('178.79.169.131'));
     $cache = $this->getMockBuilder('React\\Dns\\Query\\RecordCache')->disableOriginalConstructor()->getMock();
     $cache->expects($this->at(0))->method('lookup')->with($this->isInstanceOf('React\\Dns\\Query\\Query'))->will($this->returnValue(When::reject()));
     $cache->expects($this->at(1))->method('storeResponseMessage')->with($this->isType('integer'), $this->isInstanceOf('React\\Dns\\Model\\Message'));
     $cache->expects($this->at(2))->method('lookup')->with($this->isInstanceOf('React\\Dns\\Query\\Query'))->will($this->returnValue(When::resolve($cachedRecords)));
     $cachedExecutor = new CachedExecutor($executor, $cache);
     $query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
     $cachedExecutor->query('8.8.8.8', $query, function () {
     }, function () {
     });
     $cachedExecutor->query('8.8.8.8', $query, function () {
     }, function () {
     });
 }
예제 #9
0
 public function createSocketForAddress($address, $port, $hostName = null)
 {
     $url = $this->getSocketUrl($address, $port);
     $contextOpts = $this->contextOptions;
     // Fix for SSL in PHP >= 5.6, where peer name must be validated.
     if ($hostName !== null) {
         $contextOpts['ssl']['SNI_enabled'] = true;
         $contextOpts['ssl']['SNI_server_name'] = $hostName;
         $contextOpts['ssl']['peer_name'] = $hostName;
     }
     $flags = STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT;
     $context = stream_context_create($contextOpts);
     $socket = stream_socket_client($url, $errno, $errstr, 0, $flags, $context);
     if (!$socket) {
         return When::reject(new \RuntimeException(sprintf("connection to %s:%d failed: %s", $address, $port, $errstr), $errno));
     }
     stream_set_blocking($socket, 0);
     // wait for connection
     return $this->waitForStreamOnce($socket)->then(array($this, 'checkConnectedSocket'))->then(array($this, 'handleConnectedSocket'));
 }
예제 #10
0
 public function getConnection($host, $port)
 {
     if (strlen($host) > 255 || $port > 65535 || $port < 0) {
         return When::reject(new InvalidArgumentException('Invalid target specified'));
     }
     $deferred = new Deferred();
     $timestampTimeout = microtime(true) + $this->timeout;
     $timerTimeout = $this->loop->addTimer($this->timeout, function () use($deferred) {
         $deferred->reject(new Exception('Timeout while connecting to socks server'));
         // TODO: stop initiating connection and DNS query
     });
     // create local references as these settings may change later due to its async nature
     $auth = $this->auth;
     $protocolVersion = $this->protocolVersion;
     // protocol version not explicitly set?
     if ($protocolVersion === null) {
         // authentication requires SOCKS5, otherwise use SOCKS4a
         $protocolVersion = $auth === null ? '4a' : '5';
     }
     $loop = $this->loop;
     $that = $this;
     When::all(array($this->connector->create($this->socksHost, $this->socksPort)->then(null, function ($error) {
         throw new Exception('Unable to connect to socks server', 0, $error);
     }), $this->resolve($host)->then(null, function ($error) {
         throw new Exception('Unable to resolve remote hostname', 0, $error);
     })), function ($fulfilled) use($deferred, $port, $timestampTimeout, $that, $loop, $timerTimeout, $protocolVersion, $auth) {
         $loop->cancelTimer($timerTimeout);
         $timeout = max($timestampTimeout - microtime(true), 0.1);
         $deferred->resolve($that->handleConnectedSocks($fulfilled[0], $fulfilled[1], $port, $timeout, $protocolVersion, $auth));
     }, function ($error) use($deferred, $loop, $timerTimeout) {
         $loop->cancelTimer($timerTimeout);
         $deferred->reject(new Exception('Unable to connect to socks server', 0, $error));
     });
     return $deferred->promise();
 }