function run()
{
$fw = \Base::instance();
// Assign signal handlers
declare (ticks=1);
pcntl_signal(SIGINT, [$this, 'kill']);
pcntl_signal(SIGTERM, [$this, 'kill']);
gc_enable();
// Activate WebSocket listener
$listen = stream_socket_server($this->addr, $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $this->ctx);
$socket = socket_import_stream($listen);
register_shutdown_function(function () use($listen) {
foreach ($this->sockets as $socket) {
if ($socket != $listen) {
$this->free($socket);
}
}
$this->close($listen);
if (isset($this->events['stop']) && is_callable($func = $this->events['stop'])) {
$func($this);
}
});
if ($errstr) {
user_error($errstr, E_USER_ERROR);
}
if (isset($this->events['start']) && is_callable($func = $this->events['start'])) {
$func($this);
}
$this->sockets = [$listen];
$empty = [];
$wait = $this->wait;
while (TRUE) {
$active = $this->sockets;
$mark = microtime(TRUE);
$count = @stream_select($active, $empty, $empty, (int) $wait, round(1000000.0 * ($wait - (int) $wait)));
if (is_bool($count) && $wait) {
if (isset($this->events['error']) && is_callable($func = $this->events['error'])) {
$func($this);
}
die;
}
if ($count) {
// Process active connections
foreach ($active as $socket) {
if (!is_resource($socket)) {
continue;
}
if ($socket == $listen) {
if ($socket = @stream_socket_accept($listen, 0)) {
$this->alloc($socket);
} else {
if (isset($this->events['error']) && is_callable($func = $this->events['error'])) {
$func($this);
}
}
} else {
$id = (int) $socket;
if (isset($this->agents[$id]) && ($raw = $this->agents[$id]->fetch())) {
list($op, $data) = $raw;
// Dispatch
switch ($op & self::OpCode) {
case self::Ping:
$this->agents[$id]->send(self::Pong);
break;
case self::Close:
$this->free($socket);
break;
case self::Text:
$data = trim($data);
case self::Binary:
if (isset($this->events['receive']) && is_callable($func = $this->events['receive'])) {
$func($this->agents[$id], $op, $data);
}
break;
}
}
}
}
$wait -= microtime(TRUE) - $mark;
while ($wait < 1.0E-6) {
$wait += $this->wait;
$count = 0;
}
}
if (!$count) {
$mark = microtime(TRUE);
foreach ($this->sockets as $socket) {
if (!is_resource($socket)) {
continue;
}
$id = (int) $socket;
if ($socket != $listen && isset($this->agents[$id]) && isset($this->events['idle']) && is_callable($func = $this->events['idle'])) {
$func($this->agents[$id]);
}
}
$wait = $this->wait - microtime(TRUE) + $mark;
}
gc_collect_cycles();
}
}