Server::handleConnection()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1
Metric Value
dl 0
loc 8
ccs 5
cts 5
cp 1
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Thruster\Component\Socket;
4
5
use Thruster\Component\EventEmitter\EventEmitterTrait;
6
use Thruster\Component\EventLoop\EventLoopInterface;
7
use Thruster\Component\Socket\Exception\ConnectionException;
8
9
/**
10
 * Class Server
11
 *
12
 * @package Thruster\Component\Socket
13
 * @author  Aurimas Niekis <[email protected]>
14
 */
15
class Server implements ServerInterface
16
{
17
    use EventEmitterTrait;
18
19
    /**
20
     * @var resource
21
     */
22
    protected $socket;
23
24
    /**
25
     * @var EventLoopInterface
26
     */
27
    protected $loop;
28
29 11
    public function __construct(EventLoopInterface $loop)
30
    {
31 11
        $this->loop = $loop;
32 11
    }
33
34
    /**
35
     * {@inheritDoc}
36
     */
37 11
    public function listen(int $port, string $host = '127.0.0.1')
38
    {
39 11
        if (strpos($host, ':') !== false) {
40
            // enclose IPv6 addresses in square brackets before appending port
41 1
            $host = '[' . $host . ']';
42
        }
43
44 11
        $this->socket = @stream_socket_server("tcp://$host:$port", $errno, $errstr);
45
46 11
        if (false === $this->socket) {
47 1
            $message = sprintf(
48 1
                'Could not bind to tcp://%s:%s: %s',
49
                $host,
50
                $port,
51
                $errstr
52
            );
53
54 1
            throw new ConnectionException($message, $errno);
55
        }
56
57 11
        stream_set_blocking($this->socket, 0);
58
59 11
        $this->loop->addReadStream($this->socket, function ($master) {
60 10
            $newSocket = @stream_socket_accept($master, 0);
61
62 10
            if (false === $newSocket) {
63
                $this->emit('error', [new \RuntimeException('Error accepting new connection')]);
64
65
                return;
66
            }
67
68 10
            $this->handleConnection($newSocket);
69 11
        });
70 11
    }
71
72 10
    public function handleConnection($socket)
73
    {
74 10
        stream_set_blocking($socket, 0);
75
76 10
        $client = $this->createConnection($socket);
77
78 10
        $this->emit('connection', [$client]);
79 10
    }
80
81 11
    public function getPort() : int
82
    {
83 11
        $name = stream_socket_get_name($this->socket, false);
84
85 11
        return (int)substr(strrchr($name, ':'), 1);
86
    }
87
88 10
    public function shutdown()
89
    {
90 10
        $this->loop->removeStream($this->socket);
91
92 10
        fclose($this->socket);
93
94 10
        $this->removeListeners();
95 10
    }
96
97 10
    protected function createConnection($socket) : Connection
98
    {
99 10
        return new Connection($socket, $this->loop);
100
    }
101
102
    /**
103
     * @return resource
104
     */
105 1
    public function getSocket()
106
    {
107 1
        return $this->socket;
108
    }
109
}
110