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

StreamConnection::send()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

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