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 TCP 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 $tcpOpts = [
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    ];
45
46    /**
47     * @param array $options
48     */
49    public function __construct(array $options)
50    {
51        $this->options = \array_merge($this->options, $options);
52    }
53
54    /**
55     * @throws ConnectionException
56     */
57    public function connect(string $hostname = '') : Socket
58    {
59        $hosts = ($hostname !== '') ? [$hostname] : (array) $this->options['servers'];
60
61        $lastEx = null;
62        $tcp = null;
63        foreach ($hosts as $host) {
64            try {
65                $tcp = Socket::create($host, $this->getTcpOptions());
66                break;
67            } catch (\Exception $e) {
68                $lastEx = $e;
69            }
70        }
71
72        if ($tcp === null) {
73            throw new ConnectionException(sprintf(
74                'Unable to connect to server(s): %s',
75                implode(',', $hosts)
76            ), 0, $lastEx);
77        }
78
79        return $tcp;
80    }
81
82    /**
83     * @return array
84     */
85    protected function getTcpOptions() : array
86    {
87        $opts = [];
88
89        foreach ($this->tcpOpts as $name) {
90            if (isset($this->options[$name])) {
91                $opts[$name] = $this->options[$name];
92            }
93        }
94
95        return $opts;
96    }
97}
98