added new socket manager, errorhandling and testing is not finished yet
This commit is contained in:
42
libs/React/Socket/Connection.php
Normal file
42
libs/React/Socket/Connection.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace React\Socket;
|
||||
|
||||
use React\Stream\Stream;
|
||||
|
||||
class Connection extends Stream implements ConnectionInterface
|
||||
{
|
||||
public function handleData($stream)
|
||||
{
|
||||
// Socket is raw, not using fread as it's interceptable by filters
|
||||
// See issues #192, #209, and #240
|
||||
$data = stream_socket_recvfrom($stream, $this->bufferSize);
|
||||
if ('' !== $data && false !== $data) {
|
||||
$this->emit('data', array($data, $this));
|
||||
}
|
||||
|
||||
if ('' === $data || false === $data || !is_resource($stream) || feof($stream)) {
|
||||
$this->end();
|
||||
}
|
||||
}
|
||||
|
||||
public function handleClose()
|
||||
{
|
||||
if (is_resource($this->stream)) {
|
||||
// http://chat.stackoverflow.com/transcript/message/7727858#7727858
|
||||
stream_socket_shutdown($this->stream, STREAM_SHUT_RDWR);
|
||||
stream_set_blocking($this->stream, false);
|
||||
fclose($this->stream);
|
||||
}
|
||||
}
|
||||
|
||||
public function getRemoteAddress()
|
||||
{
|
||||
return $this->parseAddress(stream_socket_get_name($this->stream, true));
|
||||
}
|
||||
|
||||
private function parseAddress($address)
|
||||
{
|
||||
return trim(substr($address, 0, strrpos($address, ':')), '[]');
|
||||
}
|
||||
}
|
7
libs/React/Socket/ConnectionException.php
Normal file
7
libs/React/Socket/ConnectionException.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace React\Socket;
|
||||
|
||||
class ConnectionException extends \ErrorException
|
||||
{
|
||||
}
|
12
libs/React/Socket/ConnectionInterface.php
Normal file
12
libs/React/Socket/ConnectionInterface.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace React\Socket;
|
||||
|
||||
use Evenement\EventEmitterInterface;
|
||||
use React\Stream\ReadableStreamInterface;
|
||||
use React\Stream\WritableStreamInterface;
|
||||
|
||||
interface ConnectionInterface extends ReadableStreamInterface, WritableStreamInterface
|
||||
{
|
||||
public function getRemoteAddress();
|
||||
}
|
71
libs/React/Socket/Server.php
Normal file
71
libs/React/Socket/Server.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
13
libs/React/Socket/ServerInterface.php
Normal file
13
libs/React/Socket/ServerInterface.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace React\Socket;
|
||||
|
||||
use Evenement\EventEmitterInterface;
|
||||
|
||||
/** @event connection */
|
||||
interface ServerInterface extends EventEmitterInterface
|
||||
{
|
||||
public function listen($port, $host = '127.0.0.1');
|
||||
public function getPort();
|
||||
public function shutdown();
|
||||
}
|
Reference in New Issue
Block a user