1<?php
2/**
3 * This file is part of the FreeDSx Socket package.
4 *
5 * (c) Chad Sikorra <Chad.Sikorra@gmail.com>
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10
11namespace FreeDSx\Socket;
12
13use FreeDSx\Socket\Exception\ConnectionException;
14
15/**
16 * Given a selection of hosts, connect to one and return the Socket.
17 *
18 * @author Chad Sikorra <Chad.Sikorra@gmail.com>
19 */
20class SocketPool
21{
22    /**
23     * @var array
24     */
25    protected $options = [
26        'servers' => [],
27        'port' => 389,
28        'timeout_connect' => 1,
29    ];
30
31    /**
32     * @var array
33     */
34    protected $socketOpts = [
35        'use_ssl',
36        'ssl_validate_cert',
37        'ssl_allow_self_signed',
38        'ssl_ca_cert',
39        'ssl_cert',
40        'ssl_peer_name',
41        'timeout_connect',
42        'timeout_read',
43        'port',
44        'transport',
45    ];
46
47    /**
48     * @param array $options
49     */
50    public function __construct(array $options)
51    {
52        $this->options = \array_merge($this->options, $options);
53    }
54
55    /**
56     * @throws ConnectionException
57     */
58    public function connect(string $hostname = '') : Socket
59    {
60        $hosts = ($hostname !== '') ? [$hostname] : (array) $this->options['servers'];
61
62        $lastEx = null;
63        $socket = null;
64        foreach ($hosts as $host) {
65            try {
66                $socket = Socket::create(
67                    $host,
68                    $this->getSocketOptions()
69                );
70                break;
71            } catch (\Exception $e) {
72                $lastEx = $e;
73            }
74        }
75
76        if ($socket === null) {
77            throw new ConnectionException(sprintf(
78                'Unable to connect to server(s): %s',
79                implode(',', $hosts)
80            ), 0, $lastEx);
81        }
82
83        return $socket;
84    }
85
86    /**
87     * @return array
88     */
89    protected function getSocketOptions() : array
90    {
91        $opts = [];
92
93        foreach ($this->socketOpts as $name) {
94            if (isset($this->options[$name])) {
95                $opts[$name] = $this->options[$name];
96            }
97        }
98
99        return $opts;
100    }
101}
102