diff --git a/docs/changelog.rst b/docs/changelog.rst index 18dec77..ad61a91 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -4,6 +4,17 @@ Change log Unreleased_ ----------- +Changed +~~~~~~~ + +* Use version 3.x.x of ``uuid-console``. + +Fixed +~~~~~ + +* Potential for ``TelnetStream`` to be destroyed before the ``Shell`` + using it stops when lowering the maximum number of connections. + 0.1.5_ |--| 2022-11-26 ---------------------- diff --git a/library.json b/library.json index 1c291d1..cc23daf 100644 --- a/library.json +++ b/library.json @@ -29,7 +29,7 @@ "dependencies": { "nomis/uuid-common": "^1.2.0", "nomis/uuid-log": ">=2.3.0,<4", - "nomis/uuid-console": ">=1.0.1,<3" + "nomis/uuid-console": "^3.0.0" }, "build": { "flags": "-Wall -Wextra", diff --git a/src/telnet.cpp b/src/telnet.cpp index 2647f7e..1d1df37 100644 --- a/src/telnet.cpp +++ b/src/telnet.cpp @@ -78,7 +78,7 @@ TelnetService::TelnetService(std::shared_ptr commands, TelnetService::TelnetService(uint16_t port, std::shared_ptr commands, unsigned int context, unsigned int flags) : TelnetService(port, [commands, context, flags] (Stream &stream, const IPAddress &addr __attribute__((unused)), uint16_t port __attribute__((unused))) -> std::shared_ptr { - return std::make_shared(commands, stream, context, flags); + return std::make_shared(stream, commands, context, flags); }) { } @@ -115,14 +115,13 @@ size_t TelnetService::maximum_connections() const { void TelnetService::maximum_connections(size_t count) { maximum_connections_ = std::max((size_t)1, count); - while (connections_.size() > maximum_connections_) { + if (connections_.size() > maximum_connections_) { + size_t stop = connections_.size() - maximum_connections_; + for (auto it = connections_.begin(); it != connections_.end(); ) { - if (it->active()) { - it->stop(); - it = connections_.erase(it); - break; - } else { - it = connections_.erase(it); + if (it->stop()) { + if (--stop == 0) + break; } } } @@ -205,19 +204,17 @@ TelnetService::Connection::Connection(shell_factory_function &shell_factory, WiF shell->idle_timeout(idle_timeout); shell->start(); shell_ = shell; - } else { - shell_ = nullptr; } } -bool TelnetService::Connection::active() { - return shell_.use_count() > 1; -} - bool TelnetService::Connection::loop() { - if (active()) { + if (!shell_.expired()) { if (!client_.connected()) { - shell_->stop(); + auto shell = shell_.lock(); + + if (shell) { + shell->stop(); + } } return true; } else { @@ -230,9 +227,14 @@ bool TelnetService::Connection::loop() { } } -void TelnetService::Connection::stop() { - if (shell_) { - shell_->stop(); +bool TelnetService::Connection::stop() { + auto shell = shell_.lock(); + + if (shell) { + shell->stop(); + return true; + } else { + return false; } } diff --git a/src/uuid/telnet.h b/src/uuid/telnet.h index 1338ae5..e6838e9 100644 --- a/src/uuid/telnet.h +++ b/src/uuid/telnet.h @@ -389,13 +389,6 @@ class TelnetService { Connection(shell_factory_function &shell_factory, WiFiClient &&client, unsigned long idle_timeout, unsigned long write_timeout); ~Connection() = default; - /** - * Check if the shell is still active. - * - * @return Active status of the shell. - * @since 0.1.0 - */ - bool active(); /** * Stop the shell if the client is not connected. * @@ -406,9 +399,10 @@ class TelnetService { /** * Stop the shell. * - * @since 0.1.0 + * @return True if the shell had not already stopped. + * @since 0.2.0 */ - void stop(); + bool stop(); private: Connection(const Connection&) = delete; @@ -416,7 +410,7 @@ class TelnetService { WiFiClient client_; /*!< Client connection. @since 0.1.0 */ TelnetStream stream_; /*!< Telnet stream for the connection. @since 0.1.0 */ - std::shared_ptr shell_; /*!< Shell for connection. @since 0.1.0 */ + std::weak_ptr shell_; /*!< Shell for connection. @since 0.2.0 */ IPAddress addr_; /*!< Remote address of connection. @since 0.1.0 */ uint16_t port_; /*!< Remote port of connection. @since 0.1.0 */ };