Issues (32)

src/Powered/Native/Server.php (4 issues)

Labels
Severity
1
<?php
2
/**
3
 * HTTP by stream-sock server
4
 * User: moyo
5
 * Date: 08/01/2018
6
 * Time: 2:26 PM
7
 */
8
9
namespace Carno\HTTP\Powered\Native;
10
11
use Carno\HTTP\Exception\NVServerCreatingException;
12
use Carno\HTTP\Powered\Native\Parser\Requesting;
13
use Carno\HTTP\Powered\Native\Parser\Responding;
14
use Carno\HTTP\Powered\Native\Parser\Protocol;
15
use Carno\HTTP\Server\Connection as HTTPConn;
16
use Carno\Net\Address;
17
use Carno\Net\Connection as NETConn;
18
use Carno\Net\Contracts\HTTP;
19
use Carno\Net\Events;
20
use Psr\Http\Message\ResponseInterface as Response;
21
use Throwable;
22
23
class Server implements HTTP
24
{
25
    /**
26
     * @var string
27
     */
28
    private $serviced = null;
29
30
    /**
31
     * @var resource
32
     */
33
    private $listener = null;
34
35
    /**
36
     * @var Events
37
     */
38
    private $events = null;
39
40
    /**
41
     * @var int
42
     */
43
    private $idx = 0;
44
45
    /**
46
     * @var resource[]
47
     */
48
    private $fds = [];
49
50
    /**
51
     * Server constructor.
52
     * @param string $serviced
53
     * @param Address $listen
54
     * @param Events $events
55
     */
56
    public function __construct(string $serviced, Address $listen, Events $events)
57
    {
58
        $this->serviced = $serviced;
59
        $this->events = $events;
60
61
        $err = $msg = null;
62
63
        if (false ===
64
            $this->listener = stream_socket_server(
65
                sprintf('tcp://%s:%d', $listen->host(), $listen->port()),
66
                $err,
67
                $msg
68
            )
69
        ) {
70
            throw new NVServerCreatingException($msg, $err);
71
        }
72
73
        $this->events->notify(
74
            Events\Server::STARTUP,
75
            (new NETConn)
76
                ->setServiced($this->serviced)
77
                ->setLocal($listen->host(), $listen->port())
78
        );
79
    }
80
81
    /**
82
     * startup http server
83
     */
84
    public function serve() : void
85
    {
86
        swoole_event_add($this->listener, function ($server) {
0 ignored issues
show
The function swoole_event_add was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

86
        /** @scrutinizer ignore-call */ 
87
        swoole_event_add($this->listener, function ($server) {
Loading history...
87
            $this->incoming($server);
88
        });
89
    }
90
91
    /**
92
     * shutdown http server
93
     */
94
    public function shutdown() : void
95
    {
96
        swoole_event_del($this->listener);
0 ignored issues
show
The function swoole_event_del was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

96
        /** @scrutinizer ignore-call */ 
97
        swoole_event_del($this->listener);
Loading history...
97
        stream_socket_shutdown($this->listener, STREAM_SHUT_RDWR);
98
    }
99
100
    /**
101
     * @param int $conn
102
     * @param Response $response
103
     * @return bool
104
     */
105
    public function reply(int $conn, Response $response) : bool
106
    {
107
        (new Responding(new Protocol($this->fds[$conn] ?? null)))->makeResponse($response);
108
109
        if ($response->getHeaderLine('Connection') === 'close') {
110
            $this->close($conn);
111
        }
112
113
        return true;
114
    }
115
116
    /**
117
     * @param int $conn
118
     * @return bool
119
     */
120
    public function close(int $conn) : bool
121
    {
122
        if ($fd = $this->fds[$conn] ?? null) {
123
            unset($this->fds[$conn]);
124
            swoole_event_del($fd);
0 ignored issues
show
The function swoole_event_del was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

124
            /** @scrutinizer ignore-call */ 
125
            swoole_event_del($fd);
Loading history...
125
            return fclose($fd);
126
        } else {
127
            return false;
128
        }
129
    }
130
131
    /**
132
     * @param $server
133
     */
134
    private function incoming($server) : void
135
    {
136
        $idx = $this->idx += 1;
137
        swoole_event_add($this->fds[$idx] = stream_socket_accept($server), function () use ($idx) {
0 ignored issues
show
The function swoole_event_add was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

137
        /** @scrutinizer ignore-call */ 
138
        swoole_event_add($this->fds[$idx] = stream_socket_accept($server), function () use ($idx) {
Loading history...
138
            $this->receiving($idx);
139
        });
140
    }
141
142
    /**
143
     * @param int $idx
144
     */
145
    private function receiving(int $idx) : void
146
    {
147
        try {
148
            $srq = (new Requesting(new Protocol($this->fds[$idx] ?? null)))->getServerRequest();
149
            $this->events->notify(
150
                Events\HTTP::REQUESTING,
151
                (new HTTPConn)
152
                    ->setID($idx)
153
                    ->setRequest($srq)
154
                    ->setServiced($this->serviced)
155
                    ->from($this)
156
            );
157
        } catch (Throwable $e) {
158
            $this->close($idx);
159
        }
160
    }
161
}
162