Completed
Push — master ( e5c8d5...b53833 )
by Eugene
08:17
created

SocketConnection   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 83
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 76.92%

Importance

Changes 9
Bugs 1 Features 2
Metric Value
wmc 14
c 9
b 1
f 2
lcom 1
cbo 3
dl 0
loc 83
ccs 30
cts 39
cp 0.7692
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 3
A open() 0 22 3
A close() 0 7 2
A isClosed() 0 4 1
A send() 0 20 4
A createConnectionException() 0 6 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 SocketConnection implements Connection
10
{
11
    const DEFAULT_HOST = '127.0.0.1';
12
    const DEFAULT_PORT = 3301;
13
14
    private $host;
15
    private $port;
16
    private $socket;
17
18
    /**
19
     * @param string|null $host Default to '127.0.0.1'.
20
     * @param int|null    $port Default to 3301.
21
     */
22 24
    public function __construct($host = null, $port = null)
23
    {
24 24
        $this->host = null === $host ? self::DEFAULT_HOST : $host;
25 24
        $this->port = null === $port ? self::DEFAULT_PORT : $port;
26 24
    }
27
28 39
    public function open()
29
    {
30 39
        $this->close();
31
32 39
        if (false === $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) {
33
            throw new ConnectionException(sprintf(
34
                'Unable to create socket: %s.', socket_strerror(socket_last_error())
35
            ));
36
        }
37
38 39
        if (false === @socket_connect($socket, $this->host, $this->port)) {
39 2
            throw new ConnectionException(sprintf(
40 2
                'Unable to connect: %s.', socket_strerror(socket_last_error($socket))
41 2
            ));
42
        }
43
44 37
        $this->socket = $socket;
45
46 37
        $greeting = socket_read($socket, IProto::GREETING_SIZE);
47
48 37
        return IProto::parseSalt($greeting);
49
    }
50
51 39
    public function close()
52
    {
53 39
        if ($this->socket) {
54 16
            socket_close($this->socket);
55 16
            $this->socket = null;
56 16
        }
57 39
    }
58
59 101
    public function isClosed()
60
    {
61 101
        return null === $this->socket;
62
    }
63
64 100
    public function send($data)
65
    {
66 100
        if (false === socket_write($this->socket, $data, strlen($data))) {
67
            throw $this->createConnectionException();
68
        }
69
70 100
        $length = null;
71 100
        if (false === socket_recv($this->socket, $length, IProto::LENGTH_SIZE, MSG_WAITALL)) {
72
            throw $this->createConnectionException();
73
        }
74
75 100
        $length = PackUtils::unpackLength($length);
76
77 100
        $data = null;
78 100
        if (false === socket_recv($this->socket, $data, $length, MSG_WAITALL)) {
79
            throw $this->createConnectionException();
80
        }
81
82 100
        return $data;
83
    }
84
85
    private function createConnectionException()
86
    {
87
        $errorCode = socket_last_error($this->socket);
88
89
        return new ConnectionException(socket_strerror($errorCode), $errorCode);
90
    }
91
}
92