1
|
|
|
<?php |
2
|
|
|
namespace PHPDaemon\Network; |
3
|
|
|
|
4
|
|
|
use PHPDaemon\Core\Daemon; |
5
|
|
|
|
6
|
|
|
/** |
7
|
|
|
* Network server pattern |
8
|
|
|
* @package PHPDaemon\Network |
9
|
|
|
* @author Vasily Zorin <[email protected]> |
10
|
|
|
*/ |
11
|
|
|
abstract class Server extends Pool |
12
|
|
|
{ |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* @var array|null Allowed clients |
16
|
|
|
*/ |
17
|
|
|
public $allowedClients = null; |
18
|
|
|
/** |
19
|
|
|
* @var \PHPDaemon\Structures\ObjectStorage Bound sockets |
20
|
|
|
*/ |
21
|
|
|
protected $bound; |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* Constructor |
25
|
|
|
* @param array $config Config variables |
26
|
|
|
* @param boolean $init |
27
|
|
|
*/ |
28
|
|
|
public function __construct($config = [], $init = true) |
29
|
|
|
{ |
30
|
|
|
parent::__construct($config, false); |
31
|
|
|
$this->bound = new \PHPDaemon\Structures\ObjectStorage; |
32
|
|
|
if (isset($this->config->listen)) { |
33
|
|
|
$this->bindSockets($this->config->listen->value); |
|
|
|
|
34
|
|
|
} |
35
|
|
|
if ($init) { |
36
|
|
|
$this->init(); |
37
|
|
|
} |
38
|
|
|
} |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* Bind given sockets |
42
|
|
|
* @param mixed $addrs Addresses to bind |
43
|
|
|
* @param integer $max Maximum |
44
|
|
|
* @return integer Number of bound |
45
|
|
|
*/ |
46
|
|
|
public function bindSockets($addrs = [], $max = 0) |
47
|
|
|
{ |
48
|
|
|
if (is_string($addrs)) { |
49
|
|
|
$addrs = array_map('trim', explode(',', $addrs)); |
50
|
|
|
} |
51
|
|
|
$n = 0; |
52
|
|
|
foreach ($addrs as $addr) { |
|
|
|
|
53
|
|
|
if ($this->bindSocket($addr)) { |
54
|
|
|
++$n; |
55
|
|
|
} |
56
|
|
|
if ($max > 0 && ($n >= $max)) { |
57
|
|
|
return $n; |
58
|
|
|
} |
59
|
|
|
} |
60
|
|
|
return $n; |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* Bind given socket |
65
|
|
|
* @param string $uri Address to bind |
66
|
|
|
* @return boolean Success |
67
|
|
|
*/ |
68
|
|
|
public function bindSocket($uri) |
69
|
|
|
{ |
70
|
|
|
$u = \PHPDaemon\Config\_Object::parseCfgUri($uri); |
71
|
|
|
$scheme = $u['scheme']; |
72
|
|
|
if ($scheme === 'unix') { |
73
|
|
|
$socket = new \PHPDaemon\BoundSocket\UNIX($u); |
74
|
|
|
} elseif ($scheme === 'udp') { |
75
|
|
|
$socket = new \PHPDaemon\BoundSocket\UDP($u); |
76
|
|
|
if (isset($this->config->port->value)) { |
77
|
|
|
$socket->setDefaultPort($this->config->port->value); |
|
|
|
|
78
|
|
|
} |
79
|
|
|
} elseif ($scheme === 'tcp') { |
80
|
|
|
$socket = new \PHPDaemon\BoundSocket\TCP($u); |
81
|
|
|
if (isset($this->config->port->value)) { |
82
|
|
|
$socket->setDefaultPort($this->config->port->value); |
83
|
|
|
} |
84
|
|
|
} else { |
85
|
|
|
Daemon::log(get_class($this) . ': enable to bind \'' . $uri . '\': scheme \'' . $scheme . '\' is not supported'); |
86
|
|
|
return false; |
87
|
|
|
} |
88
|
|
|
$socket->attachTo($this); |
89
|
|
|
if ($socket->bindSocket()) { |
90
|
|
|
if ($this->enabled) { |
91
|
|
|
$socket->enable(); |
92
|
|
|
} |
93
|
|
|
return true; |
94
|
|
|
} |
95
|
|
|
return false; |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* Attach Generic |
100
|
|
|
* @param \PHPDaemon\BoundSocket\Generic $bound Generic |
101
|
|
|
* @param mixed $inf Info |
102
|
|
|
* @return void |
103
|
|
|
*/ |
104
|
|
|
public function attachBound(\PHPDaemon\BoundSocket\Generic $bound, $inf = null) |
105
|
|
|
{ |
106
|
|
|
$this->bound->attach($bound, $inf); |
107
|
|
|
if ($this->eventLoop !== null) { |
108
|
|
|
$bound->setEventLoop($this->eventLoop); |
109
|
|
|
} |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* Detach Generic |
114
|
|
|
* @param \PHPDaemon\BoundSocket\Generic $bound Generic |
115
|
|
|
* @return void |
116
|
|
|
*/ |
117
|
|
|
public function detachBound(\PHPDaemon\BoundSocket\Generic $bound) |
118
|
|
|
{ |
119
|
|
|
$this->bound->detach($bound); |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* Called when a request to HTTP-server looks like another connection |
124
|
|
|
* @param object $req Request |
125
|
|
|
* @param object $oldConn Connection |
126
|
|
|
* @return boolean Success |
127
|
|
|
*/ |
128
|
|
|
public function inheritFromRequest($req, $oldConn) |
129
|
|
|
{ |
130
|
|
|
if (!$oldConn || !$req) { |
131
|
|
|
return false; |
132
|
|
|
} |
133
|
|
|
$class = $this->connectionClass; |
134
|
|
|
$conn = new $class(null, $this); |
135
|
|
|
$this->attach($conn); |
136
|
|
|
$conn->setFd($oldConn->getFd(), $oldConn->getBev()); |
137
|
|
|
$oldConn->unsetFd(); |
138
|
|
|
$oldConn->pool->detach($oldConn); |
139
|
|
|
$conn->onInheritanceFromRequest($req); |
140
|
|
|
if ($req instanceof \PHPDaemon\Request\Generic) { |
141
|
|
|
$req->free(); |
142
|
|
|
} |
143
|
|
|
return true; |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* Called when ConnectionPool is finished |
148
|
|
|
* @return void |
149
|
|
|
*/ |
150
|
|
|
protected function onFinish() |
151
|
|
|
{ |
152
|
|
|
$this->closeBound(); |
153
|
|
|
parent::onFinish(); |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* Close each of binded sockets |
158
|
|
|
* @return void |
159
|
|
|
*/ |
160
|
|
|
public function closeBound() |
161
|
|
|
{ |
162
|
|
|
$this->bound->each('close'); |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* Applies config |
167
|
|
|
* @return void |
168
|
|
|
*/ |
169
|
|
|
protected function applyConfig() |
170
|
|
|
{ |
171
|
|
|
parent::applyConfig(); |
172
|
|
|
foreach ($this->config as $k => $v) { |
|
|
|
|
173
|
|
|
if (is_object($v) && $v instanceof \PHPDaemon\Config\Entry\Generic) { |
174
|
|
|
$v = $v->getValue(); |
175
|
|
|
} |
176
|
|
|
$k = strtolower($k); |
177
|
|
|
if ($k === 'allowedclients') { |
178
|
|
|
$this->allowedClients = $v; |
179
|
|
|
} |
180
|
|
|
} |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
/** |
184
|
|
|
* Called when ConnectionPool is now enabled |
185
|
|
|
* @return void |
186
|
|
|
*/ |
187
|
|
|
protected function onEnable() |
188
|
|
|
{ |
189
|
|
|
if ($this->bound) { |
190
|
|
|
$this->bound->each('enable'); |
191
|
|
|
} |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
/** |
195
|
|
|
* Called when ConnectionPool is now disabled |
196
|
|
|
* @return void |
197
|
|
|
*/ |
198
|
|
|
protected function onDisable() |
199
|
|
|
{ |
200
|
|
|
if ($this->bound) { |
201
|
|
|
$this->bound->each('disable'); |
202
|
|
|
} |
203
|
|
|
} |
204
|
|
|
} |
205
|
|
|
|
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.
If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.