72 lines
1.8 KiB
PHP
72 lines
1.8 KiB
PHP
<?php
|
|
|
|
namespace React\Socket;
|
|
|
|
use Evenement\EventEmitter;
|
|
use React\EventLoop\LoopInterface;
|
|
|
|
/** @event connection */
|
|
class Server extends EventEmitter implements ServerInterface
|
|
{
|
|
public $master;
|
|
private $loop;
|
|
|
|
public function __construct(LoopInterface $loop)
|
|
{
|
|
$this->loop = $loop;
|
|
}
|
|
|
|
public function listen($port, $host = '127.0.0.1')
|
|
{
|
|
if (strpos($host, ':') !== false) {
|
|
// enclose IPv6 addresses in square brackets before appending port
|
|
$host = '[' . $host . ']';
|
|
}
|
|
|
|
$this->master = @stream_socket_server("tcp://$host:$port", $errno, $errstr);
|
|
if (false === $this->master) {
|
|
$message = "Could not bind to tcp://$host:$port: $errstr";
|
|
throw new ConnectionException($message, $errno);
|
|
}
|
|
stream_set_blocking($this->master, 0);
|
|
|
|
$this->loop->addReadStream($this->master, function ($master) {
|
|
$newSocket = stream_socket_accept($master);
|
|
if (false === $newSocket) {
|
|
$this->emit('error', array(new \RuntimeException('Error accepting new connection')));
|
|
|
|
return;
|
|
}
|
|
$this->handleConnection($newSocket);
|
|
});
|
|
}
|
|
|
|
public function handleConnection($socket)
|
|
{
|
|
stream_set_blocking($socket, 0);
|
|
|
|
$client = $this->createConnection($socket);
|
|
|
|
$this->emit('connection', array($client));
|
|
}
|
|
|
|
public function getPort()
|
|
{
|
|
$name = stream_socket_get_name($this->master, false);
|
|
|
|
return (int) substr(strrchr($name, ':'), 1);
|
|
}
|
|
|
|
public function shutdown()
|
|
{
|
|
$this->loop->removeStream($this->master);
|
|
fclose($this->master);
|
|
$this->removeAllListeners();
|
|
}
|
|
|
|
public function createConnection($socket)
|
|
{
|
|
return new Connection($socket, $this->loop);
|
|
}
|
|
}
|