Passed
Push — master ( 981dfb...1901a1 )
by Sébastien
09:07 queued 04:13
created

StreamSocket::checkSocket()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
nc 2
nop 3
dl 0
loc 10
ccs 0
cts 0
cp 0
crap 12
rs 9.9332
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A StreamSocket::getStreamFlags() 0 3 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Soluble\Japha\Bridge\Socket;
6
7
use Soluble\Japha\Bridge\Exception\ConnectionException;
8
use Soluble\Japha\Bridge\Exception\InvalidArgumentException;
9
10
class StreamSocket implements StreamSocketInterface
11
{
12
    public const TRANSPORT_SSL = 'ssl';
13
    public const TRANSPORT_TCP = 'tcp';
14
15
    public const REGISTERED_TRANSPORTS = [
16
        self::TRANSPORT_SSL,
17
        self::TRANSPORT_TCP
18
    ];
19
20
    public const DEFAULT_CONTEXT = [
21
        'http' => [
22
            'protocol_version' => '1.1',
23
        ]
24
    ];
25
26
    public const DEFAULT_CONNECT_TIMEOUTS = [
27
        'HOST_127.0.0.1' => 5.0,
28
        'HOST_localhost' => 5.0,
29
        'DEFAULT' => 20.0
30
    ];
31
32
    /**
33
     * @var resource
34
     */
35
    protected $socket;
36
37
    protected $persistent = false;
38
    protected $address;
39
    protected $connectTimeout;
40
    protected $streamContext;
41
    protected $transport;
42
43
    /**
44
     * @param string  $transport      tcp, ssl... see self::TRANSPORT
45
     * @param string  $address        ip:port
46 32
     * @param float   $connectTimeout connection timeout in seconds (double: i.e: 5.0)
47
     * @param mixed[] $streamContext  see stream_context_create()
48
     * @param bool    $persistent     whether to use persistent connections
49
     */
50
    public function __construct(
51
        string $transport,
52
        string $address,
53 32
        float $connectTimeout = null,
54 31
        array $streamContext = self::DEFAULT_CONTEXT,
55 31
        bool $persistent = false
56 31
    ) {
57 31
        $this->setTransport($transport);
58 31
        $this->address = $address;
59 28
        $this->setConnectTimeout($connectTimeout);
60
        $this->streamContext = $streamContext;
61
        $this->persistent = $persistent;
62
        $this->createSocket();
63
    }
64 32
65
    protected function setConnectTimeout(float $timeout = null): void
66 32
    {
67 1
        if ($timeout === null) {
68 1
            list($host) = explode(':', $this->address);
69 1
            if (array_key_exists("HOST_$host", self::DEFAULT_CONNECT_TIMEOUTS)) {
70 1
                $timeout = self::DEFAULT_CONNECT_TIMEOUTS["HOST_$host"];
71
            } else {
72
                $timeout = self::DEFAULT_CONNECT_TIMEOUTS['DEFAULT'];
73 31
            }
74 31
        }
75
        $this->connectTimeout = $timeout;
76 31
    }
77
78 31
    /**
79
     * @throws InvalidArgumentException when getting an unsupported transport
80
     */
81
    protected function setTransport(string $transport): void
82
    {
83
        if (!in_array($transport, self::REGISTERED_TRANSPORTS, true)) {
84 26
            throw new InvalidArgumentException(sprintf(
85
                'Unsupported transport "%s" given (supported: %s)',
86 26
                $transport,
87
                implode(',', array_keys(self::REGISTERED_TRANSPORTS))
88
            ));
89 31
        }
90
        $this->transport = $transport;
91 31
    }
92
93
    public function getTransport(): string
94
    {
95
        return $this->transport;
96
    }
97 31
98
    public function getConnectTimeout(): float
99 31
    {
100 31
        return $this->connectTimeout;
101 31
    }
102 31
103 31
    /**
104 31
     * @return resource php socket
105 31
     */
106
    public function getSocket()
107 31
    {
108 28
        return $this->socket;
109
    }
110
111
    public function getStreamAddress(): string
112
    {
113
        return sprintf('%s://%s', $this->getTransport(), $this->address);
114
    }
115
116
    /**
117 31
     * Whether the connection is persistent or not.
118
     *
119 31
     * @return bool
120 3
     */
121 3
    public function isPersistent(): bool
122 3
    {
123 3
        return $this->persistent;
124 3
    }
125
126 3
    /**
127
     * @throws ConnectionException
128 28
     */
129
    protected function createSocket(): void
130 31
    {
131
        $socket = @stream_socket_client(
132 31
            $this->getStreamAddress(),
133
            $errno,
134
            $errstr,
135
            $this->connectTimeout,
136
            $this->getStreamFlags(),
137
            $this->getStreamContext()
138 31
        );
139
140 31
        if ($socket === false || !is_resource($socket)) {
141
            $msg = sprintf(
142
                "Could not connect to the php-java-bridge server '%s'. Please start it. (err: %s, %s)",
143
                $this->address,
144
                $errno ?? 0,
145
                $errstr ?? 'Empty errstr returned'
146
            );
147
            throw new ConnectionException($msg);
148
        }
149
150
        $this->socket = $socket;
151
    }
152
153
    protected function getStreamFlags(): int
154
    {
155
        return $this->persistent ? STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT : STREAM_CLIENT_CONNECT;
156
    }
157
158
    /**
159
     * @return resource
160
     */
161
    protected function getStreamContext()
162
    {
163
        return stream_context_create($this->streamContext);
164
    }
165
}
166