Completed
Push — master ( 5911fc...3a7e0d )
by Eugene
06:06
created

StreamConnection::send()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2.0185

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 5
cts 6
cp 0.8333
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 6
nc 2
nop 1
crap 2.0185
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 45
    public function __construct($uri = null, array $options = null)
23
    {
24 45
        $this->uri = null === $uri ? self::DEFAULT_URI : $uri;
25
26 45
        if ($options) {
27 5
            $this->options = $options + $this->options;
28
        }
29 45
    }
30
31 60
    public function open()
32
    {
33 60
        $this->close();
34
35 60
        $stream = @stream_socket_client($this->uri, $errorCode, $errorMessage, (float) $this->options['connect_timeout']);
36 60
        if (false === $stream) {
37 3
            throw new ConnectionException(sprintf('Unable to connect to %s: %s.', $this->uri, $errorMessage));
38
        }
39
40 57
        $this->stream = $stream;
41 57
        stream_set_timeout($this->stream, $this->options['socket_timeout']);
42
43 57
        $greeting = $this->read(IProto::GREETING_SIZE, 'Unable to read greeting.');
44
45 54
        return IProto::parseGreeting($greeting);
46
    }
47
48 60
    public function close()
49
    {
50 60
        if ($this->stream) {
51 17
            fclose($this->stream);
52 17
            $this->stream = null;
53
        }
54 60
    }
55
56 107
    public function isClosed()
57
    {
58 107
        return null === $this->stream;
59
    }
60
61 106
    public function send($data)
62
    {
63 106
        if (!fwrite($this->stream, $data)) {
64
            throw new ConnectionException('Unable to write request.');
65
        }
66
67 106
        $length = $this->read(IProto::LENGTH_SIZE, 'Unable to read response length.');
68 104
        $length = PackUtils::unpackLength($length);
69
70 104
        return $this->read($length, 'Unable to read response.');
71
    }
72
73 127
    private function read($length, $errorMessage)
74
    {
75 127
        if ($data = stream_get_contents($this->stream, $length)) {
76 124
            return $data;
77
        }
78
79 8
        $meta = stream_get_meta_data($this->stream);
80 8
        throw new ConnectionException($meta['timed_out'] ? 'Read timed out.' : $errorMessage);
81
    }
82
}
83