Completed
Pull Request — master (#29)
by Eugene
06:23
created

StreamConnection::close()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 0
crap 2
1
<?php
2
3
namespace Tarantool\Client\Connection;
4
5
use Tarantool\Client\Exception\ConnectionException;
6
use Tarantool\Client\IProto;
7
use Tarantool\Client\Packer\PackUtils;
8
9
class StreamConnection implements Connection
10
{
11
    const DEFAULT_URI = 'tcp://127.0.0.1:3301';
12
13
    private $uri;
14
15
    private $options = [
16
        'connect_timeout' => 10.0,
17
        'socket_timeout' => 10.0,
18
    ];
19
20
    private $stream;
21
22 41
    public function __construct($uri = null, array $options = null)
23
    {
24 41
        $this->uri = null === $uri ? self::DEFAULT_URI : $uri;
25
26 41
        if ($options) {
27 3
            $this->options = $options + $this->options;
28
        }
29 41
    }
30
31 56
    public function open()
32
    {
33 56
        $this->close();
34
35 56
        $stream = @stream_socket_client($this->uri, $errorCode, $errorMessage, (float) $this->options['connect_timeout']);
36 56
        if (false === $stream) {
37 3
            throw new ConnectionException(sprintf('Unable to connect to %s: %s.', $this->uri, $errorMessage));
38
        }
39
40 53
        $this->stream = $stream;
41 53
        stream_set_timeout($this->stream, $this->options['socket_timeout']);
42
43 53
        $greeting = $this->read(IProto::GREETING_SIZE, 'Unable to read greeting.');
44 4
45
        return IProto::parseGreeting($greeting);
46
    }
47 50
48
    public function close()
49
    {
50 56
        if ($this->stream) {
51
            fclose($this->stream);
52 56
            $this->stream = null;
53 17
        }
54 17
    }
55
56 56
    public function isClosed()
57
    {
58 103
        return null === $this->stream;
59
    }
60 103
61
    public function send($data)
62
    {
63 102
        if (!fwrite($this->stream, $data)) {
64
            throw new ConnectionException('Unable to write request.');
65 102
        }
66
67
        $length = $this->read(IProto::LENGTH_SIZE, 'Unable to read response length.');
68
        $length = PackUtils::unpackLength($length);
69 102
70
        return $this->read($length, 'Unable to read response.');
71
    }
72
73 102
    private function read($length, $errorMessage)
74
    {
75 102
        if ($data = stream_get_contents($this->stream, $length)) {
76
            return $data;
77
        }
78
79 102
        $meta = stream_get_meta_data($this->stream);
80
        throw new ConnectionException($meta['timed_out'] ? 'Read timed out.' : $errorMessage);
81
    }
82
}
83