1: <?php
2:
3: namespace React\Socket;
4:
5: use React\EventLoop\LoopInterface;
6: use React\Stream\Stream;
7: use React\Promise;
8:
9: final class SecureConnector implements ConnectorInterface
10: {
11: private $connector;
12: private $streamEncryption;
13: private $context;
14:
15: public function __construct(ConnectorInterface $connector, LoopInterface $loop, array $context = array())
16: {
17: $this->connector = $connector;
18: $this->streamEncryption = new StreamEncryption($loop, false);
19: $this->context = $context;
20: }
21:
22: public function connect($uri)
23: {
24: if (!function_exists('stream_socket_enable_crypto')) {
25: return Promise\reject(new \BadMethodCallException('Encryption not supported on your platform (HHVM < 3.8?)'));
26: }
27:
28: if (strpos($uri, '://') === false) {
29: $uri = 'tls://' . $uri;
30: }
31:
32: $parts = parse_url($uri);
33: if (!$parts || !isset($parts['scheme']) || $parts['scheme'] !== 'tls') {
34: return Promise\reject(new \InvalidArgumentException('Given URI "' . $uri . '" is invalid'));
35: }
36:
37: $uri = str_replace('tls://', '', $uri);
38: $context = $this->context;
39:
40: $encryption = $this->streamEncryption;
41: return $this->connector->connect($uri)->then(function (ConnectionInterface $connection) use ($context, $encryption) {
42:
43:
44: if (!$connection instanceof Stream) {
45: $connection->close();
46: throw new \UnexpectedValueException('Connection MUST extend Stream in order to access underlying stream resource');
47: }
48:
49:
50: foreach ($context as $name => $value) {
51: stream_context_set_option($connection->stream, 'ssl', $name, $value);
52: }
53:
54:
55: return $encryption->enable($connection)->then(null, function ($error) use ($connection) {
56:
57: $connection->close();
58: throw $error;
59: });
60: });
61: }
62: }
63: