diff options
author | marvin-borner@live.com | 2018-04-10 21:50:16 +0200 |
---|---|---|
committer | marvin-borner@live.com | 2018-04-10 21:54:48 +0200 |
commit | fc9401f04a3aca5abb22f87ebc210de8afe11d32 (patch) | |
tree | b0b310f3581764ec3955f4e496a05137a32951c3 /assets/php/vendor/react/socket/src/LimitingServer.php | |
parent | 286d643180672f20526f3dc3bd19d7b751e2fa97 (diff) |
Initial Commit
Diffstat (limited to 'assets/php/vendor/react/socket/src/LimitingServer.php')
-rw-r--r-- | assets/php/vendor/react/socket/src/LimitingServer.php | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/assets/php/vendor/react/socket/src/LimitingServer.php b/assets/php/vendor/react/socket/src/LimitingServer.php new file mode 100644 index 0000000..c7874ee --- /dev/null +++ b/assets/php/vendor/react/socket/src/LimitingServer.php @@ -0,0 +1,203 @@ +<?php + +namespace React\Socket; + +use Evenement\EventEmitter; +use Exception; +use OverflowException; + +/** + * The `LimitingServer` decorator wraps a given `ServerInterface` and is responsible + * for limiting and keeping track of open connections to this server instance. + * + * Whenever the underlying server emits a `connection` event, it will check its + * limits and then either + * - keep track of this connection by adding it to the list of + * open connections and then forward the `connection` event + * - or reject (close) the connection when its limits are exceeded and will + * forward an `error` event instead. + * + * Whenever a connection closes, it will remove this connection from the list of + * open connections. + * + * ```php + * $server = new LimitingServer($server, 100); + * $server->on('connection', function (ConnectionInterface $connection) { + * $connection->write('hello there!' . PHP_EOL); + * … + * }); + * ``` + * + * See also the `ServerInterface` for more details. + * + * @see ServerInterface + * @see ConnectionInterface + */ +class LimitingServer extends EventEmitter implements ServerInterface +{ + private $connections = array(); + private $server; + private $limit; + + private $pauseOnLimit = false; + private $autoPaused = false; + private $manuPaused = false; + + /** + * Instantiates a new LimitingServer. + * + * You have to pass a maximum number of open connections to ensure + * the server will automatically reject (close) connections once this limit + * is exceeded. In this case, it will emit an `error` event to inform about + * this and no `connection` event will be emitted. + * + * ```php + * $server = new LimitingServer($server, 100); + * $server->on('connection', function (ConnectionInterface $connection) { + * $connection->write('hello there!' . PHP_EOL); + * … + * }); + * ``` + * + * You MAY pass a `null` limit in order to put no limit on the number of + * open connections and keep accepting new connection until you run out of + * operating system resources (such as open file handles). This may be + * useful if you do not want to take care of applying a limit but still want + * to use the `getConnections()` method. + * + * You can optionally configure the server to pause accepting new + * connections once the connection limit is reached. In this case, it will + * pause the underlying server and no longer process any new connections at + * all, thus also no longer closing any excessive connections. + * The underlying operating system is responsible for keeping a backlog of + * pending connections until its limit is reached, at which point it will + * start rejecting further connections. + * Once the server is below the connection limit, it will continue consuming + * connections from the backlog and will process any outstanding data on + * each connection. + * This mode may be useful for some protocols that are designed to wait for + * a response message (such as HTTP), but may be less useful for other + * protocols that demand immediate responses (such as a "welcome" message in + * an interactive chat). + * + * ```php + * $server = new LimitingServer($server, 100, true); + * $server->on('connection', function (ConnectionInterface $connection) { + * $connection->write('hello there!' . PHP_EOL); + * … + * }); + * ``` + * + * @param ServerInterface $server + * @param int|null $connectionLimit + * @param bool $pauseOnLimit + */ + public function __construct(ServerInterface $server, $connectionLimit, $pauseOnLimit = false) + { + $this->server = $server; + $this->limit = $connectionLimit; + if ($connectionLimit !== null) { + $this->pauseOnLimit = $pauseOnLimit; + } + + $this->server->on('connection', array($this, 'handleConnection')); + $this->server->on('error', array($this, 'handleError')); + } + + /** + * Returns an array with all currently active connections + * + * ```php + * foreach ($server->getConnection() as $connection) { + * $connection->write('Hi!'); + * } + * ``` + * + * @return ConnectionInterface[] + */ + public function getConnections() + { + return $this->connections; + } + + public function getAddress() + { + return $this->server->getAddress(); + } + + public function pause() + { + if (!$this->manuPaused) { + $this->manuPaused = true; + + if (!$this->autoPaused) { + $this->server->pause(); + } + } + } + + public function resume() + { + if ($this->manuPaused) { + $this->manuPaused = false; + + if (!$this->autoPaused) { + $this->server->resume(); + } + } + } + + public function close() + { + $this->server->close(); + } + + /** @internal */ + public function handleConnection(ConnectionInterface $connection) + { + // close connection if limit exceeded + if ($this->limit !== null && count($this->connections) >= $this->limit) { + $this->handleError(new OverflowException('Connection closed because server reached connection limit')); + $connection->close(); + return; + } + + $this->connections[] = $connection; + $that = $this; + $connection->on('close', function () use ($that, $connection) { + $that->handleDisconnection($connection); + }); + + // pause accepting new connections if limit exceeded + if ($this->pauseOnLimit && !$this->autoPaused && count($this->connections) >= $this->limit) { + $this->autoPaused = true; + + if (!$this->manuPaused) { + $this->server->pause(); + } + } + + $this->emit('connection', array($connection)); + } + + /** @internal */ + public function handleDisconnection(ConnectionInterface $connection) + { + unset($this->connections[array_search($connection, $this->connections)]); + + // continue accepting new connection if below limit + if ($this->autoPaused && count($this->connections) < $this->limit) { + $this->autoPaused = false; + + if (!$this->manuPaused) { + $this->server->resume(); + } + } + } + + /** @internal */ + public function handleError(Exception $error) + { + $this->emit('error', array($error)); + } +} |