summaryrefslogtreecommitdiff
path: root/www
diff options
context:
space:
mode:
Diffstat (limited to 'www')
-rw-r--r--www/chromium/Makefile3
-rw-r--r--www/chromium/distinfo10
-rw-r--r--www/chromium/files/patch-third__party_blink_renderer_platform_runtime__enabled__features.json58
-rw-r--r--www/domoticz-devel/Makefile2
-rw-r--r--www/domoticz-devel/files/patch-pr62522178
-rw-r--r--www/domoticz/Makefile3
-rw-r--r--www/domoticz/files/patch-pr62522178
-rw-r--r--www/galene/Makefile24
-rw-r--r--www/galene/distinfo48
-rw-r--r--www/iridium/Makefile3
-rw-r--r--www/iridium/distinfo6
-rw-r--r--www/iridium/files/patch-third__party_blink_renderer_platform_runtime__enabled__features.json58
-rw-r--r--www/librewolf/Makefile5
-rw-r--r--www/librewolf/distinfo6
-rw-r--r--www/nextcloud-calendar/Makefile2
-rw-r--r--www/nextcloud-calendar/distinfo6
-rw-r--r--www/nextcloud-contacts/Makefile2
-rw-r--r--www/nextcloud-contacts/distinfo6
-rw-r--r--www/nextcloud/Makefile2
-rw-r--r--www/nextcloud/distinfo6
-rw-r--r--www/py-dj50-django-auth-ldap/Makefile2
-rw-r--r--www/py-dj50-django-auth-ldap/distinfo6
-rw-r--r--www/py-dj51-django-auth-ldap/Makefile2
-rw-r--r--www/py-dj51-django-auth-ldap/distinfo6
-rw-r--r--www/py-django-auth-ldap/Makefile4
-rw-r--r--www/py-django-auth-ldap/distinfo6
-rw-r--r--www/ungoogled-chromium/Makefile3
-rw-r--r--www/ungoogled-chromium/distinfo14
-rw-r--r--www/ungoogled-chromium/files/patch-third__party_blink_renderer_platform_runtime__enabled__features.json58
29 files changed, 4454 insertions, 103 deletions
diff --git a/www/chromium/Makefile b/www/chromium/Makefile
index 83f18761e28a..7dd66eaf8686 100644
--- a/www/chromium/Makefile
+++ b/www/chromium/Makefile
@@ -1,6 +1,5 @@
PORTNAME= chromium
-PORTVERSION= 136.0.7103.92
-PORTREVISION= 1
+PORTVERSION= 136.0.7103.113
PULSEMV= 16
PULSEV= ${PULSEMV}.1
CATEGORIES= www wayland
diff --git a/www/chromium/distinfo b/www/chromium/distinfo
index 8897a937751d..89fdf6cdec3c 100644
--- a/www/chromium/distinfo
+++ b/www/chromium/distinfo
@@ -1,7 +1,7 @@
-TIMESTAMP = 1746600351
-SHA256 (chromium-136.0.7103.92.tar.xz) = 3fa7f88ef186566948367bf1e9a9f0612e753fc69285c1654728f6a015cd4cf2
-SIZE (chromium-136.0.7103.92.tar.xz) = 7188412240
+TIMESTAMP = 1747298146
+SHA256 (chromium-136.0.7103.113.tar.xz) = 7c765bd13df842a28bb52279b8d711411ac6082151473e07bd70b9a482c0a0ac
+SIZE (chromium-136.0.7103.113.tar.xz) = 7196537592
SHA256 (pulseaudio-16.1.tar.gz) = 027266c62f2a84422ac45fa721a649508f0f1628fb1fd9242315ac54ce2d7c92
SIZE (pulseaudio-16.1.tar.gz) = 2763111
-SHA256 (chromium-136.0.7103.92-testdata.tar.xz) = 6e5bb3fba5b61ffc9e91b9d2fc9cc758bebe4d16806a68b1a32b189193c78256
-SIZE (chromium-136.0.7103.92-testdata.tar.xz) = 651393856
+SHA256 (chromium-136.0.7103.113-testdata.tar.xz) = cbf264643986db5b7aa91843ea64a1b9e23d00bb226b234d4f60788469a58ef8
+SIZE (chromium-136.0.7103.113-testdata.tar.xz) = 651614116
diff --git a/www/chromium/files/patch-third__party_blink_renderer_platform_runtime__enabled__features.json5 b/www/chromium/files/patch-third__party_blink_renderer_platform_runtime__enabled__features.json5
index a797353d5556..919aec74e31b 100644
--- a/www/chromium/files/patch-third__party_blink_renderer_platform_runtime__enabled__features.json5
+++ b/www/chromium/files/patch-third__party_blink_renderer_platform_runtime__enabled__features.json5
@@ -1,4 +1,4 @@
---- third_party/blink/renderer/platform/runtime_enabled_features.json5.orig 2025-05-05 10:57:53 UTC
+--- third_party/blink/renderer/platform/runtime_enabled_features.json5.orig 2025-05-15 08:40:59 UTC
+++ third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -434,7 +434,7 @@
name: "AppTitle",
@@ -45,7 +45,7 @@
status: "stable",
public: true,
base_feature: "none",
-@@ -4636,7 +4636,7 @@
+@@ -4635,7 +4635,7 @@
name: "UnrestrictedSharedArrayBuffer",
base_feature: "none",
origin_trial_feature_name: "UnrestrictedSharedArrayBuffer",
@@ -54,7 +54,7 @@
},
// Enables using policy-controlled feature "usb-unrestricted" to allow
// isolated context to access protected USB interface classes and to
-@@ -4811,7 +4811,7 @@
+@@ -4810,7 +4810,7 @@
{
name: "WebAppScopeExtensions",
origin_trial_feature_name: "WebAppScopeExtensions",
@@ -63,7 +63,7 @@
status: "experimental",
base_feature: "none",
},
-@@ -5086,7 +5086,7 @@
+@@ -5085,7 +5085,7 @@
{
name: "WebIdentityDigitalCredentials",
origin_trial_feature_name: "WebIdentityDigitalCredentials",
diff --git a/www/domoticz-devel/Makefile b/www/domoticz-devel/Makefile
index e8954e448702..7f56841b2567 100644
--- a/www/domoticz-devel/Makefile
+++ b/www/domoticz-devel/Makefile
@@ -11,8 +11,6 @@ WWW= https://www.domoticz.com
LICENSE= GPLv3
LICENSE_FILE= ${WRKSRC}/License.txt
-BROKEN= fails to build with Boost>=1.87
-
LIB_DEPENDS= libcurl.so:ftp/curl \
libboost_system.so:devel/boost-libs \
libjsoncpp.so:devel/jsoncpp \
diff --git a/www/domoticz-devel/files/patch-pr6252 b/www/domoticz-devel/files/patch-pr6252
new file mode 100644
index 000000000000..34c4efd3f4e4
--- /dev/null
+++ b/www/domoticz-devel/files/patch-pr6252
@@ -0,0 +1,2178 @@
+Fix for boost 1.87
+
+Removed the diff for the msbuild project files, didn't apply cleanly and not relevant anyway.
+This will merged in the next stable of domoticz.
+
+Pullrequest: https://github.com/domoticz/domoticz/pull/6252
+Patch: https://patch-diff.githubusercontent.com/raw/domoticz/domoticz/pull/6252.patch-diff
+
+diff --git hardware/ASyncSerial.cpp hardware/ASyncSerial.cpp
+index 52c950d..6147cdb 100644
+--- hardware/ASyncSerial.cpp
++++ hardware/ASyncSerial.cpp
+@@ -54,7 +54,7 @@ public:
+ {
+ }
+
+- boost::asio::io_service io; ///< Io service object
++ boost::asio::io_context io; ///< Io service object
+ boost::asio::serial_port port; ///< Serial port object
+ boost::thread backgroundThread; ///< Thread that runs read/write operations
+ bool open{ false }; ///< True if port open
+@@ -117,10 +117,10 @@ void AsyncSerial::open(const std::string& devname, unsigned int baud_rate,
+ throw;
+ }
+
+- pimpl->io.reset();
++ pimpl->io.restart();
+
+- // This gives some work to the io_service before it is started
+- pimpl->io.post([this] { return doRead(); });
++ // This gives some work to the io_context before it is started
++ boost::asio::post(pimpl->io, [this] { return doRead(); });
+
+ boost::thread t([p = &pimpl->io] { p->run(); });
+ pimpl->backgroundThread.swap(t);
+@@ -149,10 +149,10 @@ void AsyncSerial::openOnlyBaud(const std::string& devname, unsigned int baud_rat
+ throw;
+ }
+
+- pimpl->io.reset();
++ pimpl->io.restart();
+
+- //This gives some work to the io_service before it is started
+- pimpl->io.post([this] { return doRead(); });
++ //This gives some work to the io_context before it is started
++ boost::asio::post(pimpl->io, [this] { return doRead(); });
+
+ boost::thread t([p = &pimpl->io] { p->run(); });
+ pimpl->backgroundThread.swap(t);
+@@ -176,9 +176,9 @@ void AsyncSerial::close()
+ if(!isOpen()) return;
+
+ pimpl->open = false;
+- pimpl->io.post([this] { doClose(); });
++ boost::asio::post(pimpl->io, [this] { doClose(); });
+ pimpl->backgroundThread.join();
+- pimpl->io.reset();
++ pimpl->io.restart();
+ if(errorStatus())
+ {
+ throw(boost::system::system_error(boost::system::error_code(),
+@@ -192,7 +192,7 @@ void AsyncSerial::write(const char *data, size_t size)
+ std::lock_guard<std::mutex> l(pimpl->writeQueueMutex);
+ pimpl->writeQueue.insert(pimpl->writeQueue.end(),data,data+size);
+ }
+- pimpl->io.post([this] { doWrite(); });
++ boost::asio::post(pimpl->io, [this] { doWrite(); });
+ }
+
+ void AsyncSerial::write(const std::string &data)
+@@ -201,7 +201,7 @@ void AsyncSerial::write(const std::string &data)
+ std::lock_guard<std::mutex> l(pimpl->writeQueueMutex);
+ pimpl->writeQueue.insert(pimpl->writeQueue.end(), data.c_str(), data.c_str()+data.size());
+ }
+- pimpl->io.post([this] { doWrite(); });
++ boost::asio::post(pimpl->io, [this] { doWrite(); });
+ }
+
+ void AsyncSerial::write(const std::vector<char>& data)
+@@ -211,7 +211,7 @@ void AsyncSerial::write(const std::vector<char>& data)
+ pimpl->writeQueue.insert(pimpl->writeQueue.end(),data.begin(),
+ data.end());
+ }
+- pimpl->io.post([this] { doWrite(); });
++ boost::asio::post(pimpl->io, [this] { doWrite(); });
+ }
+
+ void AsyncSerial::writeString(const std::string& s)
+@@ -220,7 +220,7 @@ void AsyncSerial::writeString(const std::string& s)
+ std::lock_guard<std::mutex> l(pimpl->writeQueueMutex);
+ pimpl->writeQueue.insert(pimpl->writeQueue.end(),s.begin(),s.end());
+ }
+- pimpl->io.post([this] { doWrite(); });
++ boost::asio::post(pimpl->io, [this] { doWrite(); });
+ }
+
+ void AsyncSerial::doRead()
+diff --git hardware/ASyncSerial.h hardware/ASyncSerial.h
+index 0a51ef0..de83f8a 100644
+--- hardware/ASyncSerial.h
++++ hardware/ASyncSerial.h
+@@ -123,27 +123,27 @@ class AsyncSerial : private domoticz::noncopyable
+
+ /**
+ * Callback called to start an asynchronous read operation.
+- * This callback is called by the io_service in the spawned thread.
++ * This callback is called by the io_context in the spawned thread.
+ */
+ void doRead();
+
+ /**
+ * Callback called at the end of the asynchronous operation.
+- * This callback is called by the io_service in the spawned thread.
++ * This callback is called by the io_context in the spawned thread.
+ */
+ void readEnd(const boost::system::error_code &error, size_t bytes_transferred);
+
+ /**
+ * Callback called to start an asynchronous write operation.
+ * If it is already in progress, does nothing.
+- * This callback is called by the io_service in the spawned thread.
++ * This callback is called by the io_context in the spawned thread.
+ */
+ void doWrite();
+
+ /**
+ * Callback called at the end of an asynchronuous write operation,
+ * if there is more data to write, restarts a new write operation.
+- * This callback is called by the io_service in the spawned thread.
++ * This callback is called by the io_context in the spawned thread.
+ */
+ void writeEnd(const boost::system::error_code &error);
+
+diff --git hardware/ASyncTCP.cpp hardware/ASyncTCP.cpp
+index a375561..7c3b536 100644
+--- hardware/ASyncTCP.cpp
++++ hardware/ASyncTCP.cpp
+@@ -4,213 +4,241 @@
+ #include <boost/system/error_code.hpp> // for error_code
+ #include "../main/Logger.h"
+
+-struct hostent;
+-
+ #define MAX_TCP_BUFFER_SIZE 4096
+
+-#ifndef WIN32
+- #include <unistd.h> //gethostbyname
+-#endif
+-
+ #define STATUS_OK(err) !err
+-
+-ASyncTCP::ASyncTCP(const bool secure)
++#define STATUS_ERR(err) err
++
++ASyncTCP::ASyncTCP(const bool secure) :
++ m_Tcpwork(boost::asio::make_work_guard(m_io_context))
++ , m_Socket(m_io_context)
++ , m_Resolver(m_io_context)
++ , m_ReconnectTimer(m_io_context)
++ , m_TimeoutTimer(m_io_context)
++ , m_SendStrand(m_io_context)
+ #ifdef WWW_ENABLE_SSL
+- : mSecure(secure)
++ , m_bSecure(secure)
+ #endif
+ {
+ m_pRXBuffer = new uint8_t[MAX_TCP_BUFFER_SIZE];
+ #ifdef WWW_ENABLE_SSL
+ mContext.set_verify_mode(boost::asio::ssl::verify_none);
+- if (mSecure)
++ if (m_bSecure)
+ {
+- mSslSocket.reset(new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(mIos, mContext));
++ m_SslSocket.reset(new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(m_io_context, mContext));
+ }
+ #endif
+ }
+
+ ASyncTCP::~ASyncTCP()
+ {
+- assert(mTcpthread == nullptr);
+- mIsTerminating = true;
+- if (mTcpthread)
++ assert(m_Tcpthread == nullptr);
++ m_bIsTerminating = true;
++ if (m_Tcpthread)
+ {
+ //This should never happen. terminate() never called!!
+- _log.Log(LOG_ERROR, "ASyncTCP: Workerthread not closed. terminate() never called!!!");
+- mIos.stop();
+- if (mTcpthread)
++ _log.Log(LOG_ERROR, "ASyncTCP: Worker thread not closed. terminate() never called!!!");
++ m_io_context.stop();
++ if (m_Tcpthread)
+ {
+- mTcpthread->join();
+- mTcpthread.reset();
++ m_Tcpthread->join();
++ m_Tcpthread.reset();
+ }
+ }
+ if (m_pRXBuffer != nullptr)
+ delete[] m_pRXBuffer;
+ }
+
+-void ASyncTCP::SetReconnectDelay(int32_t Delay)
++void ASyncTCP::SetReconnectDelay(const int32_t Delay)
+ {
+- mReconnectDelay = Delay;
++ m_iReconnectDelay = Delay;
+ }
+
+ void ASyncTCP::connect(const std::string& ip, uint16_t port)
+ {
+- assert(!mSocket.is_open());
+- if (mSocket.is_open())
++ assert(!m_Socket.is_open());
++ if (m_Socket.is_open())
+ {
+ _log.Log(LOG_ERROR, "ASyncTCP: connect called while socket is still open. !!!");
+ terminate();
+ }
+
+- // RK: We reset mIos here because it might have been stopped in terminate()
+- mIos.reset();
+- // RK: After the reset, we need to provide it work anew
+- mTcpwork = std::make_shared<boost::asio::io_service::work>(mIos);
+- if (!mTcpthread)
+- mTcpthread = std::make_shared<std::thread>([p = &mIos] { p->run(); });
+-
+- mIp = ip;
+- mPort = port;
++ m_IP = ip;
++ m_Port = port;
+ std::string port_str = std::to_string(port);
+- boost::asio::ip::tcp::resolver::query query(ip, port_str);
+ timeout_start_timer();
+- mResolver.async_resolve(query, [this](auto &&err, auto &&iter) { cb_resolve_done(err, iter); });
++
++ m_Resolver.async_resolve(
++ ip, port_str,
++ [this](const boost::system::error_code& error, const boost::asio::ip::tcp::resolver::results_type& endpoints) {
++ handle_resolve(error, endpoints);
++ }
++ );
++
++ // RK: We restart m_io_context here because it might have been stopped in terminate()
++ m_io_context.restart();
++ // RK: After the reset, we need to provide it work anew
++ m_Tcpwork.reset();
++ m_Tcpwork.emplace(boost::asio::make_work_guard(m_io_context));
++ if (!m_Tcpthread)
++ m_Tcpthread = std::make_shared<std::thread>([p = &m_io_context] { p->run(); });
+ }
+
+-void ASyncTCP::cb_resolve_done(const boost::system::error_code& error, boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
++void ASyncTCP::handle_resolve(const boost::system::error_code& error, const boost::asio::ip::tcp::resolver::results_type &endpoints)
+ {
+- if (mIsTerminating) return;
++ if (m_bIsTerminating) return;
+
+- if (STATUS_OK(error))
+- {
+- connect_start(endpoint_iterator);
+- }
+- else
++ if (STATUS_ERR(error))
+ {
+ process_error(error);
++ return;
+ }
+-}
+-
+-void ASyncTCP::connect_start(boost::asio::ip::tcp::resolver::iterator& endpoint_iterator)
+-{
+- if (mIsConnected) return;
+-
+- mEndPoint = *endpoint_iterator++;
++ if (m_bIsConnected) return;
+
+ timeout_start_timer();
++
+ #ifdef WWW_ENABLE_SSL
+- if (mSecure)
++ if (m_bSecure)
+ {
+ // we reset the ssl socket, because the ssl context needs to be reinitialized after a reconnect
+- mSslSocket.reset(new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(mIos, mContext));
+- mSslSocket->lowest_layer().async_connect(mEndPoint, [this, endpoint_iterator](auto &&err) mutable { cb_connect_done(err, endpoint_iterator); });
++ m_SslSocket.reset(new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(m_io_context, mContext));
++ boost::asio::async_connect(m_SslSocket->lowest_layer(), endpoints,
++ [this](const boost::system::error_code& error, const boost::asio::ip::tcp::endpoint& endpoint)
++ {
++ handle_connect(error, endpoint);
++ }
++ );
+ }
+ else
+ #endif
+ {
+- mSocket.async_connect(mEndPoint, [this, endpoint_iterator](auto &&err) mutable { cb_connect_done(err, endpoint_iterator); });
++ boost::asio::async_connect(m_Socket, endpoints,
++ [this](const boost::system::error_code& error, const boost::asio::ip::tcp::endpoint& endpoint)
++ {
++ handle_connect(error, endpoint);
++ }
++ );
+ }
+ }
+
+-void ASyncTCP::cb_connect_done(const boost::system::error_code& error, boost::asio::ip::tcp::resolver::iterator &endpoint_iterator)
++void ASyncTCP::handle_connect(const boost::system::error_code& error, const boost::asio::ip::tcp::endpoint& /*endpoint*/)
+ {
+- if (mIsTerminating) return;
++ if (m_bIsTerminating) return;
+
+- if (STATUS_OK(error))
++ if (STATUS_ERR(error))
+ {
++ process_error(error);
++ return;
++ }
+ #ifdef WWW_ENABLE_SSL
+- if (mSecure)
+- {
+- timeout_start_timer();
+- mSslSocket->async_handshake(boost::asio::ssl::stream_base::client, [this](auto &&err) { cb_handshake_done(err); });
+- }
+- else
+-#endif
+- {
+- process_connection();
+- }
++ if (m_bSecure)
++ {
++ timeout_start_timer();
++ m_SslSocket->async_handshake(boost::asio::ssl::stream_base::client,
++ [this](const boost::system::error_code& error) {
++ cb_handshake_done(error);
++ }
++ );
+ }
+- else
++ else
++#endif
+ {
+- if (endpoint_iterator != boost::asio::ip::tcp::resolver::iterator())
+- {
+- // The connection failed. Try the next endpoint in the list.
+- connect_start(endpoint_iterator);
+- return;
+- }
+- process_error(error);
++ process_connection();
+ }
+ }
+
+ #ifdef WWW_ENABLE_SSL
+ void ASyncTCP::cb_handshake_done(const boost::system::error_code& error)
+ {
+- if (mIsTerminating) return;
++ if (m_bIsTerminating) return;
+
+- if (STATUS_OK(error))
+- {
+- process_connection();
+- }
+- else
++ if (STATUS_ERR(error))
+ {
+ process_error(error);
++ return;
+ }
++ process_connection();
++#endif
+ }
++
++void ASyncTCP::process_connection()
++{
++ m_bIsConnected = true;
++#ifdef WWW_ENABLE_SSL
++
++ if (!m_bSecure)
+ #endif
++ {
++ // RK: only if non-secure
++ boost::asio::socket_base::keep_alive option(true);
++ m_Socket.set_option(option);
++ }
++ OnConnect();
++ do_read_start();
++ do_write_start();
++}
+
+ void ASyncTCP::reconnect_start_timer()
+ {
+- if (mIsReconnecting) return;
++ if (m_bIsReconnecting) return;
+
+- if (mReconnectDelay != 0)
++ if (m_iReconnectDelay != 0)
+ {
+- mIsReconnecting = true;
+-
+- mReconnectTimer.expires_from_now(boost::posix_time::seconds(mReconnectDelay));
+- mReconnectTimer.async_wait([this](auto &&err) { cb_reconnect_start(err); });
++ m_bIsReconnecting = true;
++
++ m_ReconnectTimer.expires_from_now(boost::posix_time::seconds(m_iReconnectDelay));
++ m_ReconnectTimer.async_wait(
++ [this](const boost::system::error_code& error) {
++ cb_reconnect_start(error);
++ }
++ );
+ }
+ }
+
+ void ASyncTCP::cb_reconnect_start(const boost::system::error_code& error)
+ {
+- mIsReconnecting = false;
+- mReconnectTimer.cancel();
+- mTimeoutTimer.cancel();
++ m_bIsReconnecting = false;
++ m_ReconnectTimer.cancel();
++ m_TimeoutTimer.cancel();
+
+- if (mIsConnected) return;
++ if (m_bIsConnected) return;
+ if (error) return; // timer was cancelled
+
+ do_close();
+- connect(mIp, mPort);
++ connect(m_IP, m_Port);
+ }
+
+
+ void ASyncTCP::terminate(const bool silent)
+ {
+- mIsTerminating = true;
++ m_bIsTerminating = true;
+ disconnect(silent);
+- mTcpwork.reset();
+- mIos.stop();
+- if (mTcpthread)
++ m_Tcpwork.reset();
++ m_io_context.stop();
++ if (m_Tcpthread)
+ {
+- mTcpthread->join();
+- mTcpthread.reset();
++ m_Tcpthread->join();
++ m_Tcpthread.reset();
+ }
+- mIsReconnecting = false;
+- mIsConnected = false;
+- mWriteQ.clear();
+- mIsTerminating = false;
++ m_bIsReconnecting = false;
++ m_bIsConnected = false;
++ m_WriteQ.clear();
++ m_bIsTerminating = false;
+ }
+
+ void ASyncTCP::disconnect(const bool silent)
+ {
+- mReconnectTimer.cancel();
+- mTimeoutTimer.cancel();
+- if (!mTcpthread) return;
++ m_ReconnectTimer.cancel();
++ m_TimeoutTimer.cancel();
++ if (!m_Tcpthread) return;
+
+ try
+ {
+- mIos.post([this] { do_close(); });
++ boost::asio::post(m_io_context,
++ [this] {
++ do_close();
++ }
++ );
+ }
+ catch (...)
+ {
+@@ -223,62 +251,68 @@ void ASyncTCP::disconnect(const bool silent)
+
+ void ASyncTCP::do_close()
+ {
+- if (mIsReconnecting) {
++ if (m_bIsReconnecting) {
+ return;
+ }
+- mReconnectTimer.cancel();
+- mTimeoutTimer.cancel();
++ m_ReconnectTimer.cancel();
++ m_TimeoutTimer.cancel();
+ boost::system::error_code ec;
+ #ifdef WWW_ENABLE_SSL
+- if (mSecure)
++ if (m_bSecure)
+ {
+- if (mSslSocket->lowest_layer().is_open())
++ if (m_SslSocket->lowest_layer().is_open())
+ {
+- mSslSocket->lowest_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
+- mSslSocket->lowest_layer().close(ec);
++ m_SslSocket->lowest_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
++ m_SslSocket->lowest_layer().close(ec);
+ }
+ }
+ else
+ #endif
+ {
+- if (mSocket.is_open())
++ if (m_Socket.is_open())
+ {
+- mSocket.close(ec);
++ m_Socket.close(ec);
+ }
+ }
+ }
+
+ void ASyncTCP::do_read_start()
+ {
+- if (mIsTerminating) return;
+- if (!mIsConnected) return;
++ if (m_bIsTerminating) return;
++ if (!m_bIsConnected) return;
+
+ timeout_start_timer();
+ #ifdef WWW_ENABLE_SSL
+- if (mSecure)
++ if (m_bSecure)
+ {
+- mSslSocket->async_read_some(boost::asio::buffer(m_pRXBuffer, MAX_TCP_BUFFER_SIZE), [this](auto &&err, auto bytes) { cb_read_done(err, bytes); });
++ m_SslSocket->async_read_some(boost::asio::buffer(m_pRXBuffer, MAX_TCP_BUFFER_SIZE),
++ [this](const boost::system::error_code& error, size_t bytes_transferred) {
++ cb_read_done(error, bytes_transferred);
++ }
++ );
+ }
+ else
+ #endif
+ {
+- mSocket.async_read_some(boost::asio::buffer(m_pRXBuffer, MAX_TCP_BUFFER_SIZE), [this](auto &&err, auto bytes) { cb_read_done(err, bytes); });
++ m_Socket.async_read_some(boost::asio::buffer(m_pRXBuffer, MAX_TCP_BUFFER_SIZE),
++ [this](const boost::system::error_code& error, size_t bytes_transferred) {
++ cb_read_done(error, bytes_transferred);
++ }
++ );
+ }
+ }
+
+ void ASyncTCP::cb_read_done(const boost::system::error_code& error, size_t bytes_transferred)
+ {
+- if (mIsTerminating) return;
++ if (m_bIsTerminating) return;
+
+- if (STATUS_OK(error))
+- {
+- OnData(m_pRXBuffer, bytes_transferred);
+- do_read_start();
+- }
+- else
++ if (STATUS_ERR(error))
+ {
+ process_error(error);
++ return;
+ }
++ OnData(m_pRXBuffer, bytes_transferred);
++ do_read_start();
+ }
+
+ void ASyncTCP::write(const uint8_t* pData, size_t length)
+@@ -288,77 +322,66 @@ void ASyncTCP::write(const uint8_t* pData, size_t length)
+
+ void ASyncTCP::write(const std::string& msg)
+ {
+- if (!mTcpthread) return;
++ if (!m_Tcpthread) return;
+
+- mSendStrand.post([this, msg]() { cb_write_queue(msg); });
++ boost::asio::post(m_SendStrand, [this, msg]() { cb_write_queue(msg); });
+ }
+
+ void ASyncTCP::cb_write_queue(const std::string& msg)
+ {
+- mWriteQ.push_back(msg);
++ m_WriteQ.push_back(msg);
+
+- if (mWriteQ.size() == 1)
++ if (m_WriteQ.size() == 1)
+ do_write_start();
+ }
+
+ void ASyncTCP::do_write_start()
+ {
+- if (mIsTerminating) return;
+- if (!mIsConnected) return;
+- if (mWriteQ.empty())
++ if (m_bIsTerminating) return;
++ if (!m_bIsConnected) return;
++ if (m_WriteQ.empty())
+ return;
+
+ timeout_start_timer();
+ #ifdef WWW_ENABLE_SSL
+- if (mSecure)
++ if (m_bSecure)
+ {
+- boost::asio::async_write(*mSslSocket, boost::asio::buffer(mWriteQ.front()), [this](auto &&err, auto) { cb_write_done(err); });
++ boost::asio::async_write(*m_SslSocket, boost::asio::buffer(m_WriteQ.front()),
++ [this](const boost::system::error_code& error, std::size_t length) {
++ cb_write_done(error, length);
++ }
++ );
+ }
+ else
+ #endif
+ {
+- boost::asio::async_write(mSocket, boost::asio::buffer(mWriteQ.front()), [this](auto &&err, auto) { cb_write_done(err); });
++ boost::asio::async_write(m_Socket, boost::asio::buffer(m_WriteQ.front()),
++ [this](const boost::system::error_code& error, std::size_t length) {
++ cb_write_done(error, length);
++ }
++ );
+ }
+ }
+
+-void ASyncTCP::cb_write_done(const boost::system::error_code& error)
++void ASyncTCP::cb_write_done(const boost::system::error_code& error, std::size_t /*length*/)
+ {
+- if (mIsTerminating) return;
++ if (m_bIsTerminating) return;
+
+- if (STATUS_OK(error))
+- {
+- mWriteQ.pop_front();
+- do_write_start();
+- }
+- else
++ if (STATUS_ERR(error))
+ {
+ process_error(error);
++ return;
+ }
+-}
+-
+-void ASyncTCP::process_connection()
+-{
+- mIsConnected = true;
+-#ifdef WWW_ENABLE_SSL
+-
+- if (!mSecure)
+-#endif
+- {
+- // RK: only if non-secure
+- boost::asio::socket_base::keep_alive option(true);
+- mSocket.set_option(option);
+- }
+- OnConnect();
+- do_read_start();
++ m_WriteQ.pop_front();
+ do_write_start();
+ }
+
+ void ASyncTCP::process_error(const boost::system::error_code& error)
+ {
+ do_close();
+- if (mIsConnected)
++ if (m_bIsConnected)
+ {
+- mIsConnected = false;
++ m_bIsConnected = false;
+ OnDisconnect();
+ }
+
+@@ -369,20 +392,23 @@ void ASyncTCP::process_error(const boost::system::error_code& error)
+ reconnect_start_timer();
+ }
+
+-/* timeout methods */
+ void ASyncTCP::timeout_start_timer()
+ {
+- if (0 == mTimeoutDelay) {
++ if (0 == m_iTimeoutDelay) {
+ return;
+ }
+ timeout_cancel_timer();
+- mTimeoutTimer.expires_from_now(boost::posix_time::seconds(mTimeoutDelay));
+- mTimeoutTimer.async_wait([this](auto &&err) { timeout_handler(err); });
++ m_TimeoutTimer.expires_from_now(boost::posix_time::seconds(m_iTimeoutDelay));
++ m_TimeoutTimer.async_wait(
++ [this](const boost::system::error_code& error) {
++ timeout_handler(error);
++ }
++ );
+ }
+
+ void ASyncTCP::timeout_cancel_timer()
+ {
+- mTimeoutTimer.cancel();
++ m_TimeoutTimer.cancel();
+ }
+
+ void ASyncTCP::timeout_handler(const boost::system::error_code& error)
+@@ -397,5 +423,5 @@ void ASyncTCP::timeout_handler(const boost::system::error_code& error)
+
+ void ASyncTCP::SetTimeout(const uint32_t Timeout)
+ {
+- mTimeoutDelay = Timeout;
++ m_iTimeoutDelay = Timeout;
+ }
+diff --git hardware/ASyncTCP.h hardware/ASyncTCP.h
+index cf859bb..a8b3ae2 100644
+--- hardware/ASyncTCP.h
++++ hardware/ASyncTCP.h
+@@ -3,39 +3,31 @@
+ #include <stddef.h> // for size_t
+ #include <deque> // for write queue
+ #include <boost/asio/deadline_timer.hpp> // for deadline_timer
+-#include <boost/asio/io_service.hpp> // for io_service
++#include <boost/asio/io_context.hpp> // for io_context
+ #include <boost/asio/strand.hpp> // for strand
+ #include <boost/asio/ip/tcp.hpp> // for tcp, tcp::endpoint, tcp::s...
+ #include <boost/asio/ssl.hpp> // for secure sockets
+ #include <boost/asio/ssl/stream.hpp> // for secure sockets
+ #include <exception> // for exception
++#include <optional> // for optional
+
+ #define ASYNCTCP_THREAD_NAME "ASyncTCP"
+ #define DEFAULT_RECONNECT_TIME 30
+ #define DEFAULT_TIMEOUT_TIME 60
+
+-namespace boost
+-{
+- namespace system
+- {
+- class error_code;
+- } // namespace system
+-} // namespace boost
+-
+ class ASyncTCP
+ {
+- protected:
++protected:
+ ASyncTCP(bool secure = false);
+ virtual ~ASyncTCP();
+-
+- void connect(const std::string &hostname, uint16_t port);
++ void connect(const std::string& hostname, uint16_t port);
+ void disconnect(bool silent = true);
+- void write(const std::string &msg);
+- void write(const uint8_t *pData, size_t length);
+- void SetReconnectDelay(int32_t Delay = DEFAULT_RECONNECT_TIME);
++ void write(const std::string& msg);
++ void write(const uint8_t* pData, size_t length);
++ void SetReconnectDelay(const int32_t Delay = DEFAULT_RECONNECT_TIME);
+ bool isConnected()
+ {
+- return mIsConnected;
++ return m_bIsConnected;
+ };
+ void terminate(bool silent = true);
+ void SetTimeout(uint32_t Timeout = DEFAULT_TIMEOUT_TIME);
+@@ -43,65 +35,61 @@ class ASyncTCP
+ // Callback interface to implement in derived classes
+ virtual void OnConnect() = 0;
+ virtual void OnDisconnect() = 0;
+- virtual void OnData(const uint8_t *pData, size_t length) = 0;
+- virtual void OnError(const boost::system::error_code &error) = 0;
+-
+- boost::asio::io_service mIos; // protected to allow derived classes to attach timers etc.
++ virtual void OnData(const uint8_t* pData, size_t length) = 0;
++ virtual void OnError(const boost::system::error_code& error) = 0;
+
+- private:
+- void cb_resolve_done(const boost::system::error_code &err, boost::asio::ip::tcp::resolver::iterator endpoint_iterator);
+- void connect_start(boost::asio::ip::tcp::resolver::iterator &endpoint_iterator);
+- void cb_connect_done(const boost::system::error_code &error, boost::asio::ip::tcp::resolver::iterator &endpoint_iterator);
++ boost::asio::io_context m_io_context; // protected to allow derived classes to attach timers etc.
++private:
++ void handle_resolve(const boost::system::error_code& ec, const boost::asio::ip::tcp::resolver::results_type &results);
++ void handle_connect(const boost::system::error_code& error, const boost::asio::ip::tcp::endpoint& endpoint);
+ #ifdef WWW_ENABLE_SSL
+- void cb_handshake_done(const boost::system::error_code &error);
++ void cb_handshake_done(const boost::system::error_code& error);
+ #endif
+
+- /* timeout methods */
+ void timeout_start_timer();
+ void timeout_cancel_timer();
+ void reconnect_start_timer();
+- void timeout_handler(const boost::system::error_code &error);
++ void timeout_handler(const boost::system::error_code& error);
+
+- void cb_reconnect_start(const boost::system::error_code &error);
++ void cb_reconnect_start(const boost::system::error_code& error);
+
+ void do_close();
+
+ void do_read_start();
+- void cb_read_done(const boost::system::error_code &error, size_t bytes_transferred);
++ void cb_read_done(const boost::system::error_code& error, size_t bytes_transferred);
+
+- void cb_write_queue(const std::string &msg);
++ void cb_write_queue(const std::string& msg);
+ void do_write_start();
+- void cb_write_done(const boost::system::error_code &error);
++ void cb_write_done(const boost::system::error_code& error, size_t length);
+
+ void process_connection();
+- void process_error(const boost::system::error_code &error);
++ void process_error(const boost::system::error_code& error);
+
+- bool mIsConnected = false;
+- bool mIsReconnecting = false;
+- bool mIsTerminating = false;
++ bool m_bIsConnected = false;
++ bool m_bIsReconnecting = false;
++ bool m_bIsTerminating = false;
+
+- boost::asio::io_service::strand mSendStrand{ mIos };
+- std::deque<std::string> mWriteQ; // we need a write queue to allow concurrent writes
++ boost::asio::io_context::strand m_SendStrand;
++ std::deque<std::string> m_WriteQ; // we need a write queue to allow concurrent writes
+
+ uint8_t* m_pRXBuffer = nullptr;
+
+- int mReconnectDelay = DEFAULT_RECONNECT_TIME;
+- int mTimeoutDelay = 0;
+- boost::asio::deadline_timer mReconnectTimer{ mIos };
+- boost::asio::deadline_timer mTimeoutTimer{ mIos };
++ int m_iReconnectDelay = DEFAULT_RECONNECT_TIME;
++ int m_iTimeoutDelay = 0;
++ boost::asio::deadline_timer m_ReconnectTimer;
++ boost::asio::deadline_timer m_TimeoutTimer;
+
+- std::shared_ptr<std::thread> mTcpthread;
+- std::shared_ptr<boost::asio::io_service::work> mTcpwork;
++ std::shared_ptr<std::thread> m_Tcpthread;
++ std::optional<boost::asio::executor_work_guard<boost::asio::io_context::executor_type>> m_Tcpwork;
+
+ #ifdef WWW_ENABLE_SSL
+- const bool mSecure;
++ const bool m_bSecure;
+ boost::asio::ssl::context mContext{ boost::asio::ssl::context::sslv23 };
+- std::shared_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> mSslSocket; // the ssl socket
++ std::shared_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> m_SslSocket;
+ #endif
+- boost::asio::ip::tcp::socket mSocket{ mIos };
+- boost::asio::ip::tcp::endpoint mEndPoint;
+- boost::asio::ip::tcp::resolver mResolver{ mIos };
++ boost::asio::ip::tcp::socket m_Socket;
++ boost::asio::ip::tcp::resolver m_Resolver;
+
+- std::string mIp;
+- uint16_t mPort;
++ std::string m_IP;
++ uint16_t m_Port;
+ };
+diff --git hardware/Arilux.cpp hardware/Arilux.cpp
+index 400f5a3..20bc373 100644
+--- hardware/Arilux.cpp
++++ hardware/Arilux.cpp
+@@ -79,7 +79,7 @@ void Arilux::InsertUpdateSwitch(const std::string &lightName, const int subType,
+ {
+ uint32_t sID;
+ try {
+- sID = boost::asio::ip::address_v4::from_string(location).to_ulong();
++ sID = boost::asio::ip::make_address_v4(location).to_uint();
+ } catch (const std::exception &e) {
+ Log(LOG_ERROR, "Bad IP address: %s (%s)", location.c_str(), e.what());
+ return;
+@@ -112,8 +112,8 @@ bool Arilux::SendTCPCommand(uint32_t ip,std::vector<unsigned char> &command)
+ sum = sum & 0xFF;
+ command.push_back((unsigned char)sum);
+
+- boost::asio::io_service io_service;
+- boost::asio::ip::tcp::socket sendSocket(io_service);
++ boost::asio::io_context io_context;
++ boost::asio::ip::tcp::socket sendSocket(io_context);
+ boost::asio::ip::address_v4 address(ip);
+ boost::asio::ip::tcp::endpoint endpoint(address, 5577);
+ try
+diff --git hardware/Kodi.cpp hardware/Kodi.cpp
+index b528017..5ababf6 100644
+--- hardware/Kodi.cpp
++++ hardware/Kodi.cpp
+@@ -143,14 +143,14 @@ _eNotificationTypes CKodiNode::CKodiStatus::NotificationType()
+ }
+ }
+
+-CKodiNode::CKodiNode(boost::asio::io_service *pIos, const int pHwdID, const int PollIntervalsec, const int pTimeoutMs,
++CKodiNode::CKodiNode(boost::asio::io_context *pIoc, const int pHwdID, const int PollIntervalsec, const int pTimeoutMs,
+ const std::string& pID, const std::string& pName, const std::string& pIP, const std::string& pPort)
+ {
+ m_Busy = false;
+ m_Stoppable = false;
+ m_PlaylistPosition = 0;
+
+- m_Ios = pIos;
++ m_Ioc = pIoc;
+ m_HwdID = pHwdID;
+ m_DevID = atoi(pID.c_str());
+ sprintf(m_szDevID, "%X%02X%02X%02X", 0, 0, (m_DevID & 0xFF00) >> 8, m_DevID & 0xFF);
+@@ -581,11 +581,10 @@ void CKodiNode::handleConnect()
+ {
+ m_iMissedPongs = 0;
+ boost::system::error_code ec;
+- boost::asio::ip::tcp::resolver resolver(*m_Ios);
+- boost::asio::ip::tcp::resolver::query query(m_IP, (m_Port[0] != '-' ? m_Port : m_Port.substr(1)));
+- auto iter = resolver.resolve(query);
+- boost::asio::ip::tcp::endpoint endpoint = *iter;
+- m_Socket = new boost::asio::ip::tcp::socket(*m_Ios);
++ boost::asio::ip::tcp::resolver resolver(*m_Ioc);
++ auto iter = resolver.resolve(m_IP, (m_Port[0] != '-' ? m_Port : m_Port.substr(1)));
++ boost::asio::ip::tcp::endpoint endpoint = *iter.begin();
++ m_Socket = new boost::asio::ip::tcp::socket(*m_Ioc);
+ m_Socket->connect(endpoint, ec);
+ if (!ec)
+ {
+@@ -975,19 +974,19 @@ void CKodi::Do_Work()
+ _log.Log(LOG_NORM, "Kodi: (%s) - Restarting thread.", node->m_Name.c_str());
+ boost::thread *tAsync = new boost::thread(&CKodiNode::Do_Work, node);
+ SetThreadName(tAsync->native_handle(), "KodiNode");
+- m_ios.stop();
++ m_ioc.stop();
+ }
+ if (node->IsOn())
+ bWorkToDo = true;
+ }
+
+- if (bWorkToDo && m_ios.stopped()) // make sure that there is a boost thread to service i/o operations
++ if (bWorkToDo && m_ioc.stopped()) // make sure that there is a boost thread to service i/o operations
+ {
+- m_ios.reset();
++ m_ioc.restart();
+ // Note that this is the only thread that handles async i/o so we don't
+ // need to worry about locking or concurrency issues when processing messages
+ _log.Log(LOG_NORM, "Kodi: Restarting I/O service thread.");
+- boost::thread bt([p = &m_ios] { p->run(); });
++ boost::thread bt([p = &m_ioc] { p->run(); });
+ SetThreadName(bt.native_handle(), "KodiIO");
+ }
+ }
+@@ -1138,7 +1137,7 @@ void CKodi::ReloadNodes()
+ {
+ UnloadNodes();
+
+- m_ios.reset(); // in case this is not the first time in
++ m_ioc.restart(); // in case this is not the first time in
+
+ std::vector<std::vector<std::string> > result;
+ result = m_sql.safe_query("SELECT ID,Name,MacAddress,Timeout FROM WOLNodes WHERE (HardwareID==%d)", m_HwdID);
+@@ -1149,7 +1148,7 @@ void CKodi::ReloadNodes()
+ // create a vector to hold the nodes
+ for (const auto &sd : result)
+ {
+- auto pNode = std::make_shared<CKodiNode>(&m_ios, m_HwdID, m_iPollInterval, m_iPingTimeoutms, sd[0], sd[1], sd[2], sd[3]);
++ auto pNode = std::make_shared<CKodiNode>(&m_ioc, m_HwdID, m_iPollInterval, m_iPingTimeoutms, sd[0], sd[1], sd[2], sd[3]);
+ m_pNodes.push_back(pNode);
+ }
+ // start the threads to control each kodi
+@@ -1161,7 +1160,7 @@ void CKodi::ReloadNodes()
+ }
+ sleep_milliseconds(100);
+ _log.Log(LOG_NORM, "Kodi: Starting I/O service thread.");
+- boost::thread bt([p = &m_ios] { p->run(); });
++ boost::thread bt([p = &m_ioc] { p->run(); });
+ SetThreadName(bt.native_handle(), "KodiIO");
+ }
+ }
+@@ -1170,10 +1169,10 @@ void CKodi::UnloadNodes()
+ {
+ std::lock_guard<std::mutex> l(m_mutex);
+
+- m_ios.stop(); // stop the service if it is running
++ m_ioc.stop(); // stop the service if it is running
+ sleep_milliseconds(100);
+
+- while (((!m_pNodes.empty()) || (!m_ios.stopped())))
++ while (((!m_pNodes.empty()) || (!m_ioc.stopped())))
+ {
+ for (auto itt = m_pNodes.begin(); itt != m_pNodes.end(); ++itt)
+ {
+diff --git hardware/Kodi.h hardware/Kodi.h
+index 14f331c..4435740 100644
+--- hardware/Kodi.h
++++ hardware/Kodi.h
+@@ -150,7 +150,7 @@ class CKodiNode : public std::enable_shared_from_this<CKodiNode>, StoppableTask
+ };
+
+ public:
+- CKodiNode(boost::asio::io_service *, int, int, int, const std::string &, const std::string &, const std::string &, const std::string &);
++ CKodiNode(boost::asio::io_context *, int, int, int, const std::string &, const std::string &, const std::string &, const std::string &);
+ ~CKodiNode();
+ void Do_Work();
+ void SendCommand(const std::string &);
+@@ -207,7 +207,7 @@ class CKodiNode : public std::enable_shared_from_this<CKodiNode>, StoppableTask
+ int m_iPollIntSec;
+ int m_iMissedPongs;
+ std::string m_sLastMessage;
+- boost::asio::io_service *m_Ios;
++ boost::asio::io_context *m_Ioc;
+ boost::asio::ip::tcp::socket *m_Socket;
+ std::array<char, 256> m_Buffer;
+ };
+@@ -243,5 +243,5 @@ class CKodi : public CDomoticzHardwareBase
+ int m_iPingTimeoutms;
+ std::shared_ptr<std::thread> m_thread;
+ std::mutex m_mutex;
+- boost::asio::io_service m_ios;
++ boost::asio::io_context m_ioc;
+ };
+diff --git hardware/MQTTAutoDiscover.h hardware/MQTTAutoDiscover.h
+index 0832664..1501d6f 100644
+--- hardware/MQTTAutoDiscover.h
++++ hardware/MQTTAutoDiscover.h
+@@ -176,7 +176,7 @@ public:
+ void on_message(const struct mosquitto_message *message) override;
+ void on_connect(int rc) override;
+ void on_disconnect(int rc) override;
+- void on_going_down();
++ void on_going_down() override;
+ private:
+ void InsertUpdateSwitch(_tMQTTASensor* pSensor);
+
+diff --git hardware/PanasonicTV.cpp hardware/PanasonicTV.cpp
+index fc57d34..ce20565 100644
+--- hardware/PanasonicTV.cpp
++++ hardware/PanasonicTV.cpp
+@@ -356,18 +356,17 @@ std::string CPanasonicNode::handleWriteAndRead(const std::string& pMessageToSend
+ {
+
+ _log.Debug(DEBUG_HARDWARE, "Panasonic Plugin: (%s) Handling message: '%s'.", m_Name.c_str(), pMessageToSend.c_str());
+- boost::asio::io_service io_service;
++ boost::asio::io_context io_context;
+ // Get a list of endpoints corresponding to the server name.
+- boost::asio::ip::tcp::resolver resolver(io_service);
+- boost::asio::ip::tcp::resolver::query query(m_IP, (m_Port[0] != '-' ? m_Port : m_Port.substr(1)));
+- auto iter = resolver.resolve(query);
++ boost::asio::ip::tcp::resolver resolver(io_context);
++ auto endpoints = resolver.resolve(m_IP, (m_Port[0] != '-' ? m_Port : m_Port.substr(1)));
++ auto iter = endpoints.begin();
+ boost::asio::ip::tcp::endpoint endpoint = *iter;
+- boost::asio::ip::tcp::resolver::iterator end;
+
+ // Try each endpoint until we successfully establish a connection.
+- boost::asio::ip::tcp::socket socket(io_service);
++ boost::asio::ip::tcp::socket socket(io_context);
+ boost::system::error_code error = boost::asio::error::host_not_found;
+- while (error && iter != end)
++ while (error && iter != endpoints.end())
+ {
+ socket.close();
+ if (handleConnect(socket, *iter, error))
+@@ -1060,7 +1059,7 @@ void CPanasonic::ReloadNodes()
+ {
+ UnloadNodes();
+
+- //m_ios.reset(); // in case this is not the first time in
++ //m_ioc.reset(); // in case this is not the first time in
+
+ std::vector<std::vector<std::string> > result;
+ result = m_sql.safe_query("SELECT ID,Name,MacAddress,Timeout FROM WOLNodes WHERE (HardwareID==%d)", m_HwdID);
+@@ -1088,10 +1087,10 @@ void CPanasonic::UnloadNodes()
+ {
+ std::lock_guard<std::mutex> l(m_mutex);
+
+- m_ios.stop(); // stop the service if it is running
++ m_ioc.stop(); // stop the service if it is running
+ sleep_milliseconds(100);
+
+- while (((!m_pNodes.empty()) || (!m_ios.stopped())))
++ while (((!m_pNodes.empty()) || (!m_ioc.stopped())))
+ {
+ for (auto itt = m_pNodes.begin(); itt != m_pNodes.end(); ++itt)
+ {
+diff --git hardware/PanasonicTV.h hardware/PanasonicTV.h
+index b0a94ff..30e1ca1 100644
+--- hardware/PanasonicTV.h
++++ hardware/PanasonicTV.h
+@@ -39,7 +39,7 @@ class CPanasonic : public CDomoticzHardwareBase
+ bool m_bTryIfOff;
+ std::shared_ptr<std::thread> m_thread;
+ std::mutex m_mutex;
+- boost::asio::io_service m_ios;
++ boost::asio::io_context m_ioc;
+
+ friend class CPanasonicNode;
+ };
+diff --git hardware/Pinger.cpp hardware/Pinger.cpp
+index a66c7a1..e070b29 100644
+--- hardware/Pinger.cpp
++++ hardware/Pinger.cpp
+@@ -21,23 +21,23 @@
+ #if BOOST_VERSION >= 107000
+ #define GET_IO_SERVICE(s) ((boost::asio::io_context&)(s).get_executor().context())
+ #else
+-#define GET_IO_SERVICE(s) ((s).get_io_service())
++#define GET_IO_SERVICE(s) ((s).get_io_context())
+ #endif
+
+ class pinger
+ : private domoticz::noncopyable
+ {
+ public:
+- pinger(boost::asio::io_service &io_service, const char *destination, const int iPingTimeoutms)
++ pinger(boost::asio::io_context &io_context, const char *destination, const int iPingTimeoutms)
+ : num_replies_(0)
+ , m_PingState(false)
+- , resolver_(io_service)
+- , socket_(io_service, boost::asio::ip::icmp::v4())
+- , timer_(io_service)
++ , resolver_(io_context)
++ , socket_(io_context, boost::asio::ip::icmp::v4())
++ , timer_(io_context)
+ , sequence_number_(0)
+ {
+- boost::asio::ip::icmp::resolver::query query(boost::asio::ip::icmp::v4(), destination, "");
+- destination_ = *resolver_.resolve(query);
++ auto endpoints = resolver_.resolve(boost::asio::ip::icmp::v4(), destination, "");
++ destination_ = endpoints.begin()->endpoint();
+
+ num_tries_ = 1;
+ PingTimeoutms_ = iPingTimeoutms;
+@@ -332,11 +332,11 @@ void CPinger::ReloadNodes()
+ void CPinger::Do_Ping_Worker(const PingNode &Node)
+ {
+ bool bPingOK = false;
+- boost::asio::io_service io_service;
++ boost::asio::io_context io_context;
+ try
+ {
+- pinger p(io_service, Node.IP.c_str(), m_iPingTimeoutms);
+- io_service.run();
++ pinger p(io_context, Node.IP.c_str(), m_iPingTimeoutms);
++ io_context.run();
+ if (p.m_PingState == true)
+ {
+ bPingOK = true;
+diff --git hardware/RFLinkMQTT.h hardware/RFLinkMQTT.h
+index e938328..72433b8 100644
+--- hardware/RFLinkMQTT.h
++++ hardware/RFLinkMQTT.h
+@@ -46,7 +46,7 @@ protected:
+ boost::signals2::connection m_sDeviceReceivedConnection;
+ boost::signals2::connection m_sSwitchSceneConnection;
+ void selectNextIPAdress( void );
+- virtual bool WriteInt(const std::string &sendString); // override;
++ bool WriteInt(const std::string &sendString) override;
+ void Do_Work();
+ virtual void SendHeartbeat();
+ void StopMQTT();
+diff --git hardware/TCPProxy/tcpproxy_server.cpp hardware/TCPProxy/tcpproxy_server.cpp
+index 8aceb0b..d77d4bf 100644
+--- hardware/TCPProxy/tcpproxy_server.cpp
++++ hardware/TCPProxy/tcpproxy_server.cpp
+@@ -18,12 +18,12 @@
+ #if BOOST_VERSION >= 107000
+ #define GET_IO_SERVICE(s) ((boost::asio::io_context&)(s).get_executor().context())
+ #else
+-#define GET_IO_SERVICE(s) ((s).get_io_service())
++#define GET_IO_SERVICE(s) ((s).get_io_context())
+ #endif
+
+ namespace tcp_proxy
+ {
+- bridge::bridge(boost::asio::io_service& ios)
++ bridge::bridge(boost::asio::io_context& ios)
+ : downstream_socket_(ios),
+ upstream_socket_(ios)
+ {
+@@ -44,7 +44,7 @@ namespace tcp_proxy
+ boost::asio::ip::tcp::endpoint end;
+
+
+- boost::asio::io_service &ios= GET_IO_SERVICE(downstream_socket_);
++ boost::asio::io_context &ios= GET_IO_SERVICE(downstream_socket_);
+ boost::asio::ip::tcp::resolver resolver(ios);
+ boost::asio::ip::tcp::resolver::query query(upstream_host, upstream_port, boost::asio::ip::resolver_query_base::numeric_service);
+ auto i = resolver.resolve(query);
+@@ -137,10 +137,10 @@ namespace tcp_proxy
+ }
+ //Acceptor Class
+ acceptor::acceptor(const std::string &local_host, unsigned short local_port, const std::string &upstream_host, const std::string &upstream_port)
+- : io_service_()
++ : io_context_()
+ , m_bDoStop(false)
+ , localhost_address(boost::asio::ip::address_v4::from_string(local_host))
+- , acceptor_(io_service_, boost::asio::ip::tcp::endpoint(localhost_address, local_port))
++ , acceptor_(io_context_, boost::asio::ip::tcp::endpoint(localhost_address, local_port))
+ , upstream_host_(upstream_host)
+ , upstream_port_(upstream_port)
+ {
+@@ -151,7 +151,7 @@ namespace tcp_proxy
+ {
+ try
+ {
+- session_ = std::make_shared<bridge>(io_service_);
++ session_ = std::make_shared<bridge>(io_context_);
+ session_->sDownstreamData.connect([this](auto d, auto l) { OnDownstreamData(d, l); });
+ session_->sUpstreamData.connect([this](auto d, auto l) { OnUpstreamData(d, l); });
+
+@@ -169,11 +169,11 @@ namespace tcp_proxy
+ m_bDoStop=false;
+
+ accept_connections();
+- // The io_service::run() call will block until all asynchronous operations
++ // The io_context::run() call will block until all asynchronous operations
+ // have finished. While the server is running, there is always at least one
+ // asynchronous operation outstanding: the asynchronous accept call waiting
+ // for new incoming connections.
+- io_service_.run();
++ io_context_.run();
+ return true;
+ }
+ bool acceptor::stop()
+@@ -181,14 +181,14 @@ namespace tcp_proxy
+ m_bDoStop=true;
+ // Post a call to the stop function so that server::stop() is safe to call
+ // from any thread.
+- io_service_.post([this] { handle_stop(); });
++ io_context_.post([this] { handle_stop(); });
+ return true;
+ }
+
+ void acceptor::handle_stop()
+ {
+ // The server is stopped by canceling all outstanding asynchronous
+- // operations. Once all operations have finished the io_service::run() call
++ // operations. Once all operations have finished the io_context::run() call
+ // will exit.
+ acceptor_.close();
+ //connection_manager_.stop_all();
+diff --git hardware/TCPProxy/tcpproxy_server.h hardware/TCPProxy/tcpproxy_server.h
+index 3d1a150..148e65f 100644
+--- hardware/TCPProxy/tcpproxy_server.h
++++ hardware/TCPProxy/tcpproxy_server.h
+@@ -10,7 +10,7 @@ namespace tcp_proxy
+ class bridge : public std::enable_shared_from_this<bridge>
+ {
+ public:
+- explicit bridge(boost::asio::io_service& ios);
++ explicit bridge(boost::asio::io_context& ios);
+ boost::asio::ip::tcp::socket& downstream_socket();
+ boost::asio::ip::tcp::socket& upstream_socket();
+
+@@ -52,8 +52,8 @@ namespace tcp_proxy
+ void OnUpstreamData(const unsigned char *pData, size_t Len);
+ void OnDownstreamData(const unsigned char *pData, size_t Len);
+
+- /// The io_service used to perform asynchronous operations.
+- boost::asio::io_service io_service_;
++ /// The io_context used to perform asynchronous operations.
++ boost::asio::io_context io_context_;
+ bool m_bDoStop;
+ boost::asio::ip::address_v4 localhost_address;
+ boost::asio::ip::tcp::acceptor acceptor_;
+diff --git hardware/XiaomiDeviceSupport.h hardware/XiaomiDeviceSupport.h
+index fad7884..4a76d96 100644
+--- hardware/XiaomiDeviceSupport.h
++++ hardware/XiaomiDeviceSupport.h
+@@ -15,6 +15,7 @@
+ class XiaomiDeviceSupport
+ {
+ public:
++ virtual ~XiaomiDeviceSupport() = default;
+ /**
+ * Method to get 'model' corresponding to the ID of the device in case the Gateway API didn't provide it.
+ *
+diff --git hardware/XiaomiGateway.cpp hardware/XiaomiGateway.cpp
+index 66acdc5..fb4387a 100644
+--- hardware/XiaomiGateway.cpp
++++ hardware/XiaomiGateway.cpp
+@@ -538,12 +538,12 @@ bool XiaomiGateway::SendMessageToGateway(const std::string &controlmessage)
+ {
+ std::string message = controlmessage;
+ bool result = true;
+- boost::asio::io_service io_service;
+- boost::asio::ip::udp::socket socket_(io_service, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0));
++ boost::asio::io_context io_context;
++ boost::asio::ip::udp::socket socket_(io_context, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0));
+ stdreplace(message, "@gatewaykey", GetGatewayKey());
+ std::shared_ptr<std::string> message1(new std::string(message));
+ boost::asio::ip::udp::endpoint remote_endpoint_;
+- remote_endpoint_ = boost::asio::ip::udp::endpoint(boost::asio::ip::address::from_string(m_GatewayIp), 9898);
++ remote_endpoint_ = boost::asio::ip::udp::endpoint(boost::asio::ip::make_address_v4(m_GatewayIp), 9898);
+ socket_.send_to(boost::asio::buffer(*message1), remote_endpoint_);
+ sleep_milliseconds(150); // TODO: reduce or remove sleep
+ std::array<char, 512> recv_buffer_;
+@@ -1015,15 +1015,14 @@ bool XiaomiGateway::StopHardware()
+ void XiaomiGateway::Do_Work()
+ {
+ Log(LOG_STATUS, "XiaomiGateway (ID=%d): Worker started...", m_HwdID);
+- boost::asio::io_service io_service;
++ boost::asio::io_context io_context;
+ // Find the local ip address that is similar to the xiaomi gateway
+ try
+ {
+- boost::asio::ip::udp::resolver resolver(io_service);
+- boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), m_GatewayIp, "");
+- auto endpoints = resolver.resolve(query);
+- boost::asio::ip::udp::endpoint ep = *endpoints;
+- boost::asio::ip::udp::socket socket(io_service);
++ boost::asio::ip::udp::resolver resolver(io_context);
++ auto endpoints = resolver.resolve(boost::asio::ip::udp::v4(), m_GatewayIp, "");
++ boost::asio::ip::udp::endpoint ep = *endpoints.begin();
++ boost::asio::ip::udp::socket socket(io_context);
+ socket.connect(ep);
+ boost::asio::ip::address addr = socket.local_endpoint().address();
+ std::string compareIp = m_GatewayIp.substr(0, (m_GatewayIp.length() - 3));
+@@ -1073,11 +1072,11 @@ void XiaomiGateway::Do_Work()
+ }
+ }
+
+- XiaomiGateway::xiaomi_udp_server udp_server(io_service, m_HwdID, m_GatewayIp, m_LocalIp, m_ListenPort9898, m_OutputMessage, m_IncludeVoltage, this);
++ XiaomiGateway::xiaomi_udp_server udp_server(io_context, m_HwdID, m_GatewayIp, m_LocalIp, m_ListenPort9898, m_OutputMessage, m_IncludeVoltage, this);
+ boost::thread bt;
+ if (m_ListenPort9898)
+ {
+- bt = boost::thread([p = &io_service] { p->run(); });
++ bt = boost::thread([p = &io_context] { p->run(); });
+ SetThreadName(bt.native_handle(), "XiaomiGatewayIO");
+ }
+
+@@ -1094,7 +1093,7 @@ void XiaomiGateway::Do_Work()
+ // Log(LOG_STATUS, "sec_counter %d", sec_counter);
+ }
+ }
+- io_service.stop();
++ io_context.stop();
+ if (bt.joinable())
+ {
+ bt.join();
+@@ -1178,9 +1177,9 @@ unsigned int XiaomiGateway::GetShortID(const std::string &nodeid)
+ return sID;
+ }
+
+-XiaomiGateway::xiaomi_udp_server::xiaomi_udp_server(boost::asio::io_service &io_service, int m_HwdID, const std::string &gatewayIp, const std::string &localIp, const bool listenPort9898,
++XiaomiGateway::xiaomi_udp_server::xiaomi_udp_server(boost::asio::io_context &io_context, int m_HwdID, const std::string &gatewayIp, const std::string &localIp, const bool listenPort9898,
+ const bool outputMessage, const bool includeVoltage, XiaomiGateway *parent)
+- : socket_(io_service, boost::asio::ip::udp::v4())
++ : socket_(io_context, boost::asio::ip::udp::v4())
+ {
+ m_HardwareID = m_HwdID;
+ m_XiaomiGateway = parent;
+@@ -1196,8 +1195,8 @@ XiaomiGateway::xiaomi_udp_server::xiaomi_udp_server(boost::asio::io_service &io_
+ if (!m_localip.empty())
+ {
+ boost::system::error_code ec;
+- boost::asio::ip::address listen_addr = boost::asio::ip::address::from_string(m_localip, ec);
+- boost::asio::ip::address mcast_addr = boost::asio::ip::address::from_string("224.0.0.50", ec);
++ boost::asio::ip::address listen_addr = boost::asio::ip::make_address_v4(m_localip, ec);
++ boost::asio::ip::address mcast_addr = boost::asio::ip::make_address_v4("224.0.0.50", ec);
+ boost::asio::ip::udp::endpoint listen_endpoint(mcast_addr, 9898);
+
+ socket_.bind(boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 9898));
+@@ -1213,9 +1212,9 @@ XiaomiGateway::xiaomi_udp_server::xiaomi_udp_server(boost::asio::io_service &io_
+ socket_.bind(boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 9898));
+ std::shared_ptr<std::string> message(new std::string(R"({"cmd":"whois"})"));
+ boost::asio::ip::udp::endpoint remote_endpoint;
+- remote_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::address::from_string("224.0.0.50"), 4321);
++ remote_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::make_address_v4("224.0.0.50"), 4321);
+ socket_.send_to(boost::asio::buffer(*message), remote_endpoint);
+- socket_.set_option(boost::asio::ip::multicast::join_group(boost::asio::ip::address::from_string("224.0.0.50")));
++ socket_.set_option(boost::asio::ip::multicast::join_group(boost::asio::ip::make_address_v4("224.0.0.50")));
+ }
+ }
+ catch (const boost::system::system_error &ex)
+@@ -1720,7 +1719,7 @@ void XiaomiGateway::xiaomi_udp_server::handle_receive(const boost::system::error
+ message.append("\"}");
+ std::shared_ptr<std::string> message1(new std::string(message));
+ boost::asio::ip::udp::endpoint remote_endpoint;
+- remote_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::address::from_string(TrueGateway->GetGatewayIp().c_str()), 9898);
++ remote_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::make_address_v4(TrueGateway->GetGatewayIp().c_str()), 9898);
+ socket_.send_to(boost::asio::buffer(*message1), remote_endpoint);
+ }
+ }
+@@ -1746,7 +1745,7 @@ void XiaomiGateway::xiaomi_udp_server::handle_receive(const boost::system::error
+ std::string message = R"({"cmd" : "get_id_list"})";
+ std::shared_ptr<std::string> message2(new std::string(message));
+ boost::asio::ip::udp::endpoint remote_endpoint;
+- remote_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::address::from_string(TrueGateway->GetGatewayIp().c_str()), 9898);
++ remote_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::make_address_v4(TrueGateway->GetGatewayIp().c_str()), 9898);
+ socket_.send_to(boost::asio::buffer(*message2), remote_endpoint);
+ }
+ }
+diff --git hardware/XiaomiGateway.h hardware/XiaomiGateway.h
+index dce4b34..1f552f3 100644
+--- hardware/XiaomiGateway.h
++++ hardware/XiaomiGateway.h
+@@ -100,7 +100,7 @@ class XiaomiGateway : public CDomoticzHardwareBase
+ class xiaomi_udp_server
+ {
+ public:
+- xiaomi_udp_server(boost::asio::io_service &io_service, int m_HwdID, const std::string &gatewayIp, const std::string &localIp, bool listenPort9898, bool outputMessage,
++ xiaomi_udp_server(boost::asio::io_context &io_context, int m_HwdID, const std::string &gatewayIp, const std::string &localIp, bool listenPort9898, bool outputMessage,
+ bool includeVolage, XiaomiGateway *parent);
+ ~xiaomi_udp_server() = default;
+
+diff --git hardware/Yeelight.cpp hardware/Yeelight.cpp
+index cdb7889..e5fe8fc 100644
+--- hardware/Yeelight.cpp
++++ hardware/Yeelight.cpp
+@@ -93,8 +93,8 @@ void Yeelight::Do_Work()
+
+ try
+ {
+- boost::asio::io_service io_service;
+- udp_server server(io_service, m_HwdID);
++ boost::asio::io_context io_context;
++ udp_server server(io_context, m_HwdID);
+ int sec_counter = YEELIGHT_POLL_INTERVAL - 5;
+ while (!IsStopRequested(1000))
+ {
+@@ -105,7 +105,7 @@ void Yeelight::Do_Work()
+ if (sec_counter % 60 == 0) //poll YeeLights every minute
+ {
+ server.start_send();
+- io_service.run();
++ io_context.run();
+ }
+ }
+ }
+@@ -227,12 +227,11 @@ bool Yeelight::WriteToHardware(const char *pdata, const unsigned char length)
+
+ try
+ {
+- boost::asio::io_service io_service;
+- boost::asio::ip::tcp::socket sendSocket(io_service);
+- boost::asio::ip::tcp::resolver resolver(io_service);
+- boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), szTmp, "55443");
+- auto iterator = resolver.resolve(query);
+- boost::asio::connect(sendSocket, iterator);
++ boost::asio::io_context io_context;
++ boost::asio::ip::tcp::socket sendSocket(io_context);
++ boost::asio::ip::tcp::resolver resolver(io_context);
++ auto endpoints = resolver.resolve(boost::asio::ip::tcp::v4(), szTmp, "55443");
++ boost::asio::connect(sendSocket, endpoints);
+
+ std::string message;
+ std::string message2;
+@@ -404,8 +403,8 @@ bool Yeelight::WriteToHardware(const char *pdata, const unsigned char length)
+ std::array<char, 1024> recv_buffer_;
+ int hardwareId;
+
+-Yeelight::udp_server::udp_server(boost::asio::io_service& io_service, int m_HwdID)
+- : socket_(io_service, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0))
++Yeelight::udp_server::udp_server(boost::asio::io_context& io_context, int m_HwdID)
++ : socket_(io_context, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0))
+ {
+ socket_.set_option(boost::asio::ip::udp::socket::reuse_address(true));
+ socket_.set_option(boost::asio::socket_base::broadcast(true));
+@@ -421,7 +420,7 @@ void Yeelight::udp_server::start_send()
+ //Log(LOG_STATUS, "start_send..................");
+ std::shared_ptr<std::string> message(
+ new std::string(testMessage));
+- remote_endpoint_ = boost::asio::ip::udp::endpoint(boost::asio::ip::address::from_string("239.255.255.250"), 1982);
++ remote_endpoint_ = boost::asio::ip::udp::endpoint(boost::asio::ip::make_address_v4("239.255.255.250"), 1982);
+ socket_.send_to(boost::asio::buffer(*message), remote_endpoint_);
+ sleep_milliseconds(150);
+ start_receive();
+diff --git hardware/Yeelight.h hardware/Yeelight.h
+index fb03c28..3b7b4c3 100644
+--- hardware/Yeelight.h
++++ hardware/Yeelight.h
+@@ -25,7 +25,7 @@ class Yeelight : public CDomoticzHardwareBase
+ class udp_server
+ {
+ public:
+- udp_server(boost::asio::io_service &io_service, int m_HwdID);
++ udp_server(boost::asio::io_context &io_context, int m_HwdID);
+ boost::asio::ip::udp::socket socket_;
+ boost::asio::ip::udp::endpoint remote_endpoint_;
+ void start_send();
+diff --git hardware/plugins/PluginManager.cpp hardware/plugins/PluginManager.cpp
+index 2813112..423edbb 100644
+--- hardware/plugins/PluginManager.cpp
++++ hardware/plugins/PluginManager.cpp
+@@ -64,7 +64,7 @@ namespace Plugins {
+ // PyMODINIT_FUNC PyInit_DomoticzEvents(void);
+
+ std::mutex PluginMutex; // controls accessto the message queue and m_pPlugins map
+- boost::asio::io_service ios;
++ boost::asio::io_context ios;
+
+ std::map<int, CDomoticzHardwareBase*> CPluginSystem::m_pPlugins;
+ std::map<std::string, std::string> CPluginSystem::m_PluginXml;
+@@ -315,7 +315,7 @@ namespace Plugins {
+ // Create initial IO Service thread
+ ios.restart();
+ // Create some work to keep IO Service alive
+- auto work = boost::asio::io_service::work(ios);
++ auto work = boost::asio::make_work_guard(ios);
+ boost::thread_group BoostThreads;
+ for (int i = 0; i < 1; i++)
+ {
+diff --git hardware/plugins/PluginTransports.cpp hardware/plugins/PluginTransports.cpp
+index 52d14e7..f7ace0f 100644
+--- hardware/plugins/PluginTransports.cpp
++++ hardware/plugins/PluginTransports.cpp
+@@ -116,15 +116,14 @@ namespace Plugins {
+ m_bConnected = false;
+ m_Socket = new boost::asio::ip::tcp::socket(ios);
+
+- boost::system::error_code ec;
+- boost::asio::ip::tcp::resolver::query query(m_IP, m_Port);
+- auto iter = m_Resolver.resolve(query);
+- boost::asio::ip::tcp::endpoint endpoint = *iter;
+-
+ //
+ // Async resolve/connect based on http://www.boost.org/doc/libs/1_45_0/doc/html/boost_asio/example/http/client/async_client.cpp
+ //
+- m_Resolver.async_resolve(query, [this](auto &&err, auto end) { handleAsyncResolve(err, end); });
++ m_Resolver.async_resolve(m_IP, m_Port,
++ [this](auto &&err, auto endpoints) {
++ handleAsyncResolve(err, endpoints);
++ }
++ );
+ }
+ }
+ catch (std::exception& e)
+@@ -139,15 +138,14 @@ namespace Plugins {
+ return true;
+ }
+
+- void CPluginTransportTCP::handleAsyncResolve(const boost::system::error_code & err, boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
++ void CPluginTransportTCP::handleAsyncResolve(const boost::system::error_code & err, boost::asio::ip::tcp::resolver::results_type endpoints)
+ {
+ CPlugin* pPlugin = ((CConnection*)m_pConnection)->pPlugin;
+ AccessPython Guard(pPlugin, "CPluginTransportTCP::handleAsyncResolve");
+
+ if (!err)
+ {
+- boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator;
+- m_Socket->async_connect(endpoint, [this, endpoint_iterator](auto &&err) mutable { handleAsyncConnect(err, ++endpoint_iterator); });
++ boost::asio::async_connect(*m_Socket, endpoints, [this](auto &&err, const boost::asio::ip::tcp::endpoint &endpoint) mutable { handleAsyncConnect(err, endpoint); });
+ }
+ else
+ {
+@@ -169,7 +167,7 @@ namespace Plugins {
+ }
+ }
+
+- void CPluginTransportTCP::handleAsyncConnect(const boost::system::error_code &err, const boost::asio::ip::tcp::resolver::iterator &endpoint_iterator)
++ void CPluginTransportTCP::handleAsyncConnect(const boost::system::error_code &err, const boost::asio::ip::tcp::endpoint &endpoint)
+ {
+ CPlugin* pPlugin = ((CConnection*)m_pConnection)->pPlugin;
+ AccessPython Guard(pPlugin, "CPluginTransportTCP::handleAsyncResolve");
+@@ -481,7 +479,7 @@ namespace Plugins {
+ }
+ };
+
+- void CPluginTransportTCPSecure::handleAsyncConnect(const boost::system::error_code &err, const boost::asio::ip::tcp::resolver::iterator &endpoint_iterator)
++ void CPluginTransportTCPSecure::handleAsyncConnect(const boost::system::error_code &err, const boost::asio::ip::tcp::endpoint &endpoint)
+ {
+ CPlugin* pPlugin = ((CConnection*)m_pConnection)->pPlugin;
+ if (!pPlugin) return;
+@@ -498,7 +496,7 @@ namespace Plugins {
+ SSL_set_tlsext_host_name(m_TLSSock->native_handle(), m_IP.c_str()); // Enable SNI
+
+ m_TLSSock->set_verify_mode(boost::asio::ssl::verify_none);
+- m_TLSSock->set_verify_callback(boost::asio::ssl::rfc2818_verification(m_IP));
++ m_TLSSock->set_verify_callback(boost::asio::ssl::host_name_verification(m_IP));
+ // m_TLSSock->set_verify_callback([this](auto v, auto &c){ VerifyCertificate(v, c);});
+ try
+ {
+@@ -648,7 +646,7 @@ namespace Plugins {
+ // Hanlde multicast
+ if (((m_IP.substr(0, 4) >= "224.") && (m_IP.substr(0, 4) <= "239.")) || (m_IP.substr(0, 4) == "255."))
+ {
+- m_Socket->set_option(boost::asio::ip::multicast::join_group(boost::asio::ip::address::from_string(m_IP.c_str())), ec);
++ m_Socket->set_option(boost::asio::ip::multicast::join_group(boost::asio::ip::make_address_v4(m_IP.c_str())), ec);
+ m_Socket->set_option(boost::asio::ip::multicast::hops(2), ec);
+ }
+ }
+@@ -764,7 +762,7 @@ namespace Plugins {
+ }
+ else
+ {
+- boost::asio::ip::udp::endpoint destination(boost::asio::ip::address::from_string(m_IP.c_str()), atoi(m_Port.c_str()));
++ boost::asio::ip::udp::endpoint destination(boost::asio::ip::make_address_v4(m_IP.c_str()), atoi(m_Port.c_str()));
+ size_t bytes_transferred = m_Socket->send_to(boost::asio::buffer(pMessage, pMessage.size()), destination);
+ }
+ }
+@@ -825,12 +823,14 @@ namespace Plugins {
+ }
+ };
+
+- void CPluginTransportICMP::handleAsyncResolve(const boost::system::error_code &ec, const boost::asio::ip::icmp::resolver::iterator &endpoint_iterator)
++ void CPluginTransportICMP::handleAsyncResolve(const boost::system::error_code &ec, boost::asio::ip::icmp::resolver::results_type endpoints)
+ {
+ if (!ec)
+ {
++ m_Endpoint = endpoints.begin()->endpoint();
++ m_IP = m_Endpoint.address().to_string();
++
+ m_bConnected = true;
+- m_IP = endpoint_iterator->endpoint().address().to_string();
+
+ // Listen will fail (10022 - bad parameter) unless something has been sent(?)
+ std::string body("ping");
+@@ -857,15 +857,11 @@ namespace Plugins {
+ m_bConnecting = true;
+ m_Socket = new boost::asio::ip::icmp::socket(ios, boost::asio::ip::icmp::v4());
+
+- boost::system::error_code ec;
+- boost::asio::ip::icmp::resolver::query query(boost::asio::ip::icmp::v4(), m_IP, "");
+- auto iter = m_Resolver.resolve(query);
+- m_Endpoint = *iter;
+-
+- //
+- // Async resolve/connect based on http://www.boost.org/doc/libs/1_51_0/doc/html/boost_asio/example/icmp/ping.cpp
+- //
+- m_Resolver.async_resolve(query, [this](auto &&err, auto i) { handleAsyncResolve(err, i); });
++ m_Resolver.async_resolve(boost::asio::ip::icmp::v4(), m_IP, "",
++ [this](auto &&err, auto endpoints) {
++ handleAsyncResolve(err, endpoints);
++ }
++ );
+ }
+ else
+ {
+diff --git hardware/plugins/PluginTransports.h hardware/plugins/PluginTransports.h
+index c1cc1e3..79d5725 100644
+--- hardware/plugins/PluginTransports.h
++++ hardware/plugins/PluginTransports.h
+@@ -6,7 +6,7 @@
+
+ namespace Plugins {
+
+- extern boost::asio::io_service ios;
++ extern boost::asio::io_context ios;
+
+ class CPluginTransport
+ {
+@@ -85,8 +85,8 @@ namespace Plugins {
+ , m_Socket(nullptr){};
+ bool handleConnect() override;
+ bool handleListen() override;
+- virtual void handleAsyncResolve(const boost::system::error_code &err, boost::asio::ip::tcp::resolver::iterator endpoint_iterator);
+- virtual void handleAsyncConnect(const boost::system::error_code &err, const boost::asio::ip::tcp::resolver::iterator &endpoint_iterator);
++ virtual void handleAsyncResolve(const boost::system::error_code &err, boost::asio::ip::tcp::resolver::results_type endpoints);
++ virtual void handleAsyncConnect(const boost::system::error_code &err, const boost::asio::ip::tcp::endpoint &endpoint);
+ virtual void handleAsyncAccept(boost::asio::ip::tcp::socket *pSocket, const boost::system::error_code &error);
+ void handleRead(const boost::system::error_code &e, std::size_t bytes_transferred) override;
+ void handleWrite(const std::vector<byte> &pMessage) override;
+@@ -111,7 +111,7 @@ namespace Plugins {
+ : CPluginTransportTCP(HwdID, pConnection, Address, Port)
+ , m_Context(nullptr)
+ , m_TLSSock(nullptr){};
+- void handleAsyncConnect(const boost::system::error_code &err, const boost::asio::ip::tcp::resolver::iterator &endpoint_iterator) override;
++ void handleAsyncConnect(const boost::system::error_code &err, const boost::asio::ip::tcp::endpoint &endpoint) override;
+ void handleRead(const boost::system::error_code &e, std::size_t bytes_transferred) override;
+ void handleWrite(const std::vector<byte> &pMessage) override;
+ ~CPluginTransportTCPSecure() override;
+@@ -151,7 +151,7 @@ namespace Plugins {
+ , m_Socket(nullptr)
+ , m_Timer(nullptr)
+ , m_SequenceNo(-1){};
+- void handleAsyncResolve(const boost::system::error_code &err, const boost::asio::ip::icmp::resolver::iterator &endpoint_iterator);
++ void handleAsyncResolve(const boost::system::error_code &err, boost::asio::ip::icmp::resolver::results_type endpoints);
+ bool handleListen() override;
+ void handleTimeout(const boost::system::error_code &) override;
+ void handleRead(const boost::system::error_code &e, std::size_t bytes_transferred) override;
+diff --git main/WebServerCmds.cpp main/WebServerCmds.cpp
+index 7d4a9f2..3586373 100644
+--- main/WebServerCmds.cpp
++++ main/WebServerCmds.cpp
+@@ -1632,7 +1632,7 @@ namespace http
+ ExtraHeaders.push_back("App_Revision: " + std::to_string(iAppRevision));
+ ExtraHeaders.push_back("System_Name: " + systemname);
+ ExtraHeaders.push_back("Machine: " + machine);
+- ExtraHeaders.push_back("Type: " + (!bIsBetaChannel) ? "Stable" : "Beta");
++ ExtraHeaders.push_back("Type: " + std::string(!bIsBetaChannel ? "Stable" : "Beta"));
+
+ if (!HTTPClient::GET(szHistoryURL, ExtraHeaders, historyfile))
+ {
+diff --git main/mainworker.cpp main/mainworker.cpp
+index b5027eb..b8f8dc7 100644
+--- main/mainworker.cpp
++++ main/mainworker.cpp
+@@ -1318,7 +1318,7 @@ bool MainWorker::IsUpdateAvailable(const bool bIsForced)
+ ExtraHeaders.push_back("App_Revision: " + std::to_string(iAppRevision));
+ ExtraHeaders.push_back("System_Name: " + m_szSystemName);
+ ExtraHeaders.push_back("Machine: " + machine);
+- ExtraHeaders.push_back("Type: " + (!bIsBetaChannel) ? "Stable" : "Beta");
++ ExtraHeaders.push_back("Type: " + std::string(!bIsBetaChannel ? "Stable" : "Beta"));
+
+ if (!HTTPClient::GET(szURL, ExtraHeaders, revfile))
+ return false;
+diff --git plugins/examples/Pinger.py plugins/examples/Pinger.py
+index 6b54559..c7a776d 100644
+--- plugins/examples/Pinger.py
++++ plugins/examples/Pinger.py
+@@ -3,7 +3,7 @@
+ # Author: Dnpwwo, 2017 - 2018
+ #
+ """
+-<plugin key="ICMP" name="Pinger (ICMP)" author="dnpwwo" version="3.1.4">
++<plugin key="ICMP" name="Pinger (ICMP)" author="dnpwwo" version="3.1.5">
+ <description>
+ ICMP Pinger Plugin.<br/><br/>
+ Specify comma delimted addresses (IP or DNS names) of devices that are to be pinged.<br/>
+@@ -144,8 +144,9 @@ class BasePlugin:
+ for Device in Devices:
+ if (("Name" in Devices[Device].Options) and (Devices[Device].Options["Name"] == Connection.Name)):
+ UpdateDevice(Device, 0, "Off", TimedOut)
+- self.icmpConn.Close()
+- self.icmpConn = None
++ if (self.icmpConn != None):
++ self.icmpConn.Close()
++ self.icmpConn = None
+
+ def onHeartbeat(self):
+ Domoticz.Debug("Heartbeating...")
+diff --git push/MQTTPush.h push/MQTTPush.h
+index 0773b43..d9f9332 100644
+--- push/MQTTPush.h
++++ push/MQTTPush.h
+@@ -14,7 +14,7 @@ public:
+ void on_message(const struct mosquitto_message* message) override;
+ void on_connect(int rc) override;
+ void on_disconnect(int rc) override;
+- void on_going_down();
++ void on_going_down() override;
+ private:
+ struct _tPushItem
+ {
+diff --git tcpserver/TCPClient.cpp tcpserver/TCPClient.cpp
+index d55da10..3eee093 100644
+--- tcpserver/TCPClient.cpp
++++ tcpserver/TCPClient.cpp
+@@ -19,7 +19,7 @@ namespace tcp {
+ delete socket_;
+ }
+
+- CTCPClient::CTCPClient(boost::asio::io_service& ios, CTCPServerIntBase* pManager)
++ CTCPClient::CTCPClient(boost::asio::io_context& ios, CTCPServerIntBase* pManager)
+ : CTCPClientBase(pManager)
+ {
+ socket_ = new boost::asio::ip::tcp::socket(ios);
+diff --git tcpserver/TCPClient.h tcpserver/TCPClient.h
+index df4350d..e7a882b 100644
+--- tcpserver/TCPClient.h
++++ tcpserver/TCPClient.h
+@@ -38,7 +38,7 @@ class CTCPClient : public CTCPClientBase,
+ public std::enable_shared_from_this<CTCPClient>
+ {
+ public:
+- CTCPClient(boost::asio::io_service& ios, CTCPServerIntBase *pManager);
++ CTCPClient(boost::asio::io_context& ios, CTCPServerIntBase *pManager);
+ ~CTCPClient() = default;
+ void start() override;
+ void stop() override;
+diff --git tcpserver/TCPServer.cpp tcpserver/TCPServer.cpp
+index 91fdc7e..57f8709 100644
+--- tcpserver/TCPServer.cpp
++++ tcpserver/TCPServer.cpp
+@@ -18,14 +18,14 @@ namespace tcp {
+
+ CTCPServerInt::CTCPServerInt(const std::string& address, const std::string& port, CTCPServer* pRoot) :
+ CTCPServerIntBase(pRoot),
+- io_service_(),
+- acceptor_(io_service_)
++ io_context_(),
++ acceptor_(io_context_)
+ {
+ // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
+- boost::asio::ip::tcp::resolver resolver(io_service_);
+- boost::asio::ip::tcp::resolver::query query(address, port);
+- boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
+- acceptor_.open(endpoint.protocol());
++ boost::asio::ip::tcp::resolver resolver(io_context_);
++ boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::results_type endpoints = resolver.resolve(address, port);
++ auto endpoint = *endpoints.begin();
++ acceptor_.open(endpoint.endpoint().protocol());
+ acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+ // bind to both ipv6 and ipv4 sockets for the "::" address only
+ if (address == "::")
+@@ -35,7 +35,7 @@ namespace tcp {
+ acceptor_.bind(endpoint);
+ acceptor_.listen();
+
+- new_connection_ = std::make_shared<CTCPClient>(io_service_, this);
++ new_connection_ = std::make_shared<CTCPClient>(io_context_, this);
+ if (new_connection_ == nullptr)
+ {
+ _log.Log(LOG_ERROR, "Error creating new client!");
+@@ -47,24 +47,24 @@ namespace tcp {
+
+ void CTCPServerInt::start()
+ {
+- // The io_service::run() call will block until all asynchronous operations
++ // The io_context::run() call will block until all asynchronous operations
+ // have finished. While the server is running, there is always at least one
+ // asynchronous operation outstanding: the asynchronous accept call waiting
+ // for new incoming connections.
+- io_service_.run();
++ io_context_.run();
+ }
+
+ void CTCPServerInt::stop()
+ {
+ // Post a call to the stop function so that server::stop() is safe to call
+ // from any thread.
+- io_service_.post([this] { handle_stop(); });
++ boost::asio::post([this] { handle_stop(); });
+ }
+
+ void CTCPServerInt::handle_stop()
+ {
+ // The server is stopped by cancelling all outstanding asynchronous
+- // operations. Once all operations have finished the io_service::run() call
++ // operations. Once all operations have finished the io_context::run() call
+ // will exit.
+ acceptor_.close();
+ stopAllClients();
+@@ -88,7 +88,7 @@ namespace tcp {
+ connections_.insert(new_connection_);
+ new_connection_->start();
+
+- new_connection_.reset(new CTCPClient(io_service_, this));
++ new_connection_.reset(new CTCPClient(io_context_, this));
+
+ acceptor_.async_accept(*(new_connection_->socket()), [this](auto&& err) { handleAccept(err); });
+ }
+diff --git tcpserver/TCPServer.h tcpserver/TCPServer.h
+index ca611b1..17284ca 100644
+--- tcpserver/TCPServer.h
++++ tcpserver/TCPServer.h
+@@ -70,8 +70,8 @@ private:
+ /// Handle a request to stop the server.
+ void handle_stop();
+
+- /// The io_service used to perform asynchronous operations.
+- boost::asio::io_service io_service_;
++ /// The io_context used to perform asynchronous operations.
++ boost::asio::io_context io_context_;
+
+ boost::asio::ip::tcp::acceptor acceptor_;
+
+diff --git webserver/cWebem.cpp webserver/cWebem.cpp
+index 57d9683..c0d292d 100644
+--- webserver/cWebem.cpp
++++ webserver/cWebem.cpp
+@@ -47,13 +47,13 @@ namespace http {
+ , myRequestHandler(doc_root, this)
+ // Rene, make sure we initialize m_sessions first, before starting a server
+ , myServer(server_factory::create(settings, myRequestHandler))
+- , m_io_service()
+- , m_session_clean_timer(m_io_service, boost::posix_time::minutes(1))
++ , m_io_context()
++ , m_session_clean_timer(m_io_context, boost::posix_time::minutes(1))
+ {
+ // associate handler to timer and schedule the first iteration
+ m_session_clean_timer.async_wait([this](auto &&) { CleanSessions(); });
+- m_io_service_thread = std::make_shared<std::thread>([p = &m_io_service] { p->run(); });
+- SetThreadName(m_io_service_thread->native_handle(), "Webem_ssncleaner");
++ m_io_context_thread = std::make_shared<std::thread>([p = &m_io_context] { p->run(); });
++ SetThreadName(m_io_context_thread->native_handle(), "Webem_ssncleaner");
+ }
+
+ cWebem::~cWebem()
+@@ -93,14 +93,14 @@ namespace http {
+ // Stop session cleaner
+ try
+ {
+- if (!m_io_service.stopped())
++ if (!m_io_context.stopped())
+ {
+- m_io_service.stop();
++ m_io_context.stop();
+ }
+- if (m_io_service_thread)
++ if (m_io_context_thread)
+ {
+- m_io_service_thread->join();
+- m_io_service_thread.reset();
++ m_io_context_thread->join();
++ m_io_context_thread.reset();
+ }
+ }
+ catch (...)
+diff --git webserver/cWebem.h webserver/cWebem.h
+index 6e3b899..7905c45 100644
+--- webserver/cWebem.h
++++ webserver/cWebem.h
+@@ -259,9 +259,9 @@ namespace http
+ std::string m_webRoot;
+ /// sessions management
+ std::mutex m_sessionsMutex;
+- boost::asio::io_service m_io_service;
++ boost::asio::io_context m_io_context;
+ boost::asio::deadline_timer m_session_clean_timer;
+- std::shared_ptr<std::thread> m_io_service_thread;
++ std::shared_ptr<std::thread> m_io_context_thread;
+ };
+
+ } // namespace server
+diff --git webserver/connection.cpp webserver/connection.cpp
+index 40f9788..3a70924 100644
+--- webserver/connection.cpp
++++ webserver/connection.cpp
+@@ -22,13 +22,13 @@ namespace http {
+ extern time_t last_write_time(const std::string& path);
+
+ // this is the constructor for plain connections
+- connection::connection(boost::asio::io_service &io_service, connection_manager &manager, request_handler &handler, int read_timeout)
++ connection::connection(boost::asio::io_context &io_context, connection_manager &manager, request_handler &handler, int read_timeout)
+ : send_buffer_(nullptr)
+ , read_timeout_(read_timeout)
+- , read_timer_(io_service, boost::posix_time::seconds(read_timeout))
++ , read_timer_(io_context, boost::posix_time::seconds(read_timeout))
+ , default_abandoned_timeout_(20 * 60)
+ // 20mn before stopping abandoned connection
+- , abandoned_timer_(io_service, boost::posix_time::seconds(default_abandoned_timeout_))
++ , abandoned_timer_(io_context, boost::posix_time::seconds(default_abandoned_timeout_))
+ , connection_manager_(manager)
+ , request_handler_(handler)
+ , status_(INITIALIZING)
+@@ -39,18 +39,18 @@ namespace http {
+ keepalive_ = false;
+ write_in_progress = false;
+ connection_type = ConnectionType::connection_http;
+- socket_ = std::make_unique<boost::asio::ip::tcp::socket>(io_service);
++ socket_ = std::make_unique<boost::asio::ip::tcp::socket>(io_context);
+ }
+
+ #ifdef WWW_ENABLE_SSL
+ // this is the constructor for secure connections
+- connection::connection(boost::asio::io_service &io_service, connection_manager &manager, request_handler &handler, int read_timeout, boost::asio::ssl::context &context)
++ connection::connection(boost::asio::io_context &io_context, connection_manager &manager, request_handler &handler, int read_timeout, boost::asio::ssl::context &context)
+ : send_buffer_(nullptr)
+ , read_timeout_(read_timeout)
+- , read_timer_(io_service, boost::posix_time::seconds(read_timeout))
++ , read_timer_(io_context, boost::posix_time::seconds(read_timeout))
+ , default_abandoned_timeout_(20 * 60)
+ // 20mn before stopping abandoned connection
+- , abandoned_timer_(io_service, boost::posix_time::seconds(default_abandoned_timeout_))
++ , abandoned_timer_(io_context, boost::posix_time::seconds(default_abandoned_timeout_))
+ , connection_manager_(manager)
+ , request_handler_(handler)
+ , status_(INITIALIZING)
+@@ -62,7 +62,7 @@ namespace http {
+ write_in_progress = false;
+ connection_type = ConnectionType::connection_http;
+ socket_ = nullptr;
+- sslsocket_ = std::make_unique<ssl_socket>(io_service, context);
++ sslsocket_ = std::make_unique<ssl_socket>(io_context, context);
+ }
+ #endif
+
+@@ -152,9 +152,9 @@ namespace http {
+ if (error != boost::asio::error::operation_aborted) {
+ switch (connection_type) {
+ case ConnectionType::connection_http:
+- // Timers should be cancelled before stopping to remove tasks from the io_service.
+- // The io_service will stop naturally when every tasks are removed.
+- // If timers are not cancelled, the exception ERROR_ABANDONED_WAIT_0 is thrown up to the io_service::run() caller.
++ // Timers should be cancelled before stopping to remove tasks from the io_context.
++ // The io_context will stop naturally when every tasks are removed.
++ // If timers are not cancelled, the exception ERROR_ABANDONED_WAIT_0 is thrown up to the io_context::run() caller.
+ cancel_abandoned_timeout();
+ cancel_read_timeout();
+
+@@ -372,7 +372,7 @@ namespace http {
+ switch (connection_type)
+ {
+ case ConnectionType::connection_http:
+- begin = boost::asio::buffer_cast<const char*>(_buf.data());
++ begin = static_cast<const char*>(_buf.data().data());
+ try
+ {
+ request_parser_.reset();
+@@ -404,7 +404,7 @@ namespace http {
+ newt = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
+ }
+
+- size_t sizeread = begin - boost::asio::buffer_cast<const char*>(_buf.data());
++ size_t sizeread = begin - static_cast<const char*>(_buf.data().data());
+ _buf.consume(sizeread);
+ reply_.reset();
+ const char* pConnection = request_.get_req_header(&request_, "Connection");
+@@ -520,7 +520,7 @@ namespace http {
+ break;
+ case ConnectionType::connection_websocket:
+ case ConnectionType::connection_websocket_closing:
+- begin = boost::asio::buffer_cast<const char*>(_buf.data());
++ begin = static_cast<const char*>(_buf.data().data());
+ result = websocket_parser.parse((const unsigned char*)begin, _buf.size(), bytes_consumed, keepalive_);
+ _buf.consume(bytes_consumed);
+ if (result) {
+diff --git webserver/connection.hpp webserver/connection.hpp
+index ce452b5..c1a82c5 100644
+--- webserver/connection.hpp
++++ webserver/connection.hpp
+@@ -43,11 +43,11 @@ namespace http {
+ std::string host_local_endpoint_port_;
+ std::string host_last_request_uri_;
+ };
+- /// Construct a connection with the given io_service.
+- explicit connection(boost::asio::io_service& io_service,
++ /// Construct a connection with the given io_context.
++ explicit connection(boost::asio::io_context& io_context,
+ connection_manager& manager, request_handler& handler, int timeout);
+ #ifdef WWW_ENABLE_SSL
+- explicit connection(boost::asio::io_service& io_service,
++ explicit connection(boost::asio::io_context& io_context,
+ connection_manager& manager, request_handler& handler, int timeout, boost::asio::ssl::context& context);
+ #endif
+ ~connection() = default;
+diff --git webserver/server.cpp webserver/server.cpp
+index da15887..8bdfc13 100644
+--- webserver/server.cpp
++++ webserver/server.cpp
+@@ -13,15 +13,15 @@ namespace http {
+ namespace server {
+
+ server_base::server_base(const server_settings &settings, request_handler &user_request_handler)
+- : io_service_()
+- , acceptor_(io_service_)
++ : io_context_()
++ , acceptor_(io_context_)
+ , request_handler_(user_request_handler)
+ , settings_(settings)
+ , timeout_(20)
+ , // default read timeout in seconds
+ is_running(false)
+ , is_stop_complete(false)
+- , m_heartbeat_timer(io_service_)
++ , m_heartbeat_timer(io_context_)
+ {
+ if (!settings.is_enabled())
+ {
+@@ -39,10 +39,10 @@ namespace server {
+ }
+
+ // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
+- boost::asio::ip::tcp::resolver resolver(io_service_);
+- boost::asio::ip::tcp::resolver::query query(settings_.listening_address, settings_.listening_port);
+- boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
+- acceptor_.open(endpoint.protocol());
++ boost::asio::ip::tcp::resolver resolver(io_context_);
++ boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::results_type endpoints = resolver.resolve(settings_.listening_address, settings_.listening_port);
++ auto endpoint = *endpoints.begin();
++ acceptor_.open(endpoint.endpoint().protocol());
+ acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+ // bind to both ipv6 and ipv4 sockets for the "::" address only
+ if (settings_.listening_address == "::")
+@@ -59,28 +59,28 @@ namespace server {
+ }
+
+ void server_base::run() {
+- // The io_service::run() call will block until all asynchronous operations
++ // The io_context::run() call will block until all asynchronous operations
+ // have finished. While the server is running, there is always at least one
+ // asynchronous operation outstanding: the asynchronous accept call waiting
+ // for new incoming connections.
+ try {
+ is_running = true;
+ heart_beat(boost::system::error_code());
+- io_service_.run();
++ io_context_.run();
+ is_running = false;
+ } catch (std::exception& e) {
+ _log.Log(LOG_ERROR, "[web:%s] exception occurred : '%s' (need to run again)", settings_.listening_port.c_str(), e.what());
+ is_running = false;
+ // Note: if acceptor is up everything is OK, we can call run() again
+ // but if the exception has broken the acceptor we cannot stop/start it and the next run() will exit immediatly.
+- io_service_.reset(); // this call is needed before calling run() again
++ io_context_.restart(); // this call is needed before calling run() again
+ throw;
+ } catch (...) {
+ _log.Log(LOG_ERROR, "[web:%s] unknown exception occurred (need to run again)", settings_.listening_port.c_str());
+ is_running = false;
+ // Note: if acceptor is up everything is OK, we can call run() again
+ // but if the exception has broken the acceptor we cannot stop/start it and the next run() will exit immediatly.
+- io_service_.reset(); // this call is needed before calling run() again
++ io_context_.restart(); // this call is needed before calling run() again
+ throw;
+ }
+ }
+@@ -89,12 +89,12 @@ void server_base::run() {
+ void server_base::stop() {
+ if (is_running) {
+ // Post a call to the stop function so that server_base::stop() is safe to call from any thread.
+- // Rene, set is_running to false, because the following is an io_service call, which makes is_running
++ // Rene, set is_running to false, because the following is an io_context call, which makes is_running
+ // never set to false whilst in the call itself
+ is_running = false;
+- io_service_.post([this] { handle_stop(); });
++ boost::asio::post(io_context_, [this] { handle_stop(); });
+ } else {
+- // if io_service is not running then the post call will not be performed
++ // if io_context is not running then the post call will not be performed
+ handle_stop();
+ }
+
+@@ -112,7 +112,7 @@ void server_base::stop() {
+ }
+ sleep_milliseconds(500);
+ }
+- io_service_.stop();
++ io_context_.stop();
+
+ // Deregister heartbeat
+ m_mainworker.HeartbeatRemove(std::string("WebServer:") + settings_.listening_port);
+@@ -136,7 +136,7 @@ void server_base::heart_beat(const boost::system::error_code& error)
+ m_mainworker.HeartbeatUpdate(std::string("WebServer:") + settings_.listening_port);
+
+ // Schedule next heartbeat
+- m_heartbeat_timer.expires_from_now(std::chrono::seconds(4));
++ m_heartbeat_timer.expires_after(std::chrono::seconds(4));
+ m_heartbeat_timer.async_wait([this](auto &&err) { heart_beat(err); });
+ }
+ }
+@@ -148,7 +148,7 @@ server::server(const server_settings &settings, request_handler &user_request_ha
+ }
+
+ void server::init_connection() {
+- new_connection_.reset(new connection(io_service_, connection_manager_, request_handler_, timeout_));
++ new_connection_.reset(new connection(io_context_, connection_manager_, request_handler_, timeout_));
+ }
+
+ /**
+@@ -157,7 +157,7 @@ void server::init_connection() {
+ void server::handle_accept(const boost::system::error_code& e) {
+ if (!e) {
+ connection_manager_.start(new_connection_);
+- new_connection_.reset(new connection(io_service_,
++ new_connection_.reset(new connection(io_context_,
+ connection_manager_, request_handler_, timeout_));
+ // listen for a subsequent request
+ acceptor_.async_accept(new_connection_->socket(), [this](auto &&err) { handle_accept(err); });
+@@ -267,7 +267,7 @@ void ssl_server::init_connection() {
+ } else {
+ _log.Log(LOG_ERROR, "[web:%s] missing SSL DH parameters file %s!", settings_.listening_port.c_str(), settings_.tmp_dh_file_path.c_str());
+ }
+- new_connection_.reset(new connection(io_service_, connection_manager_, request_handler_, timeout_, context_));
++ new_connection_.reset(new connection(io_context_, connection_manager_, request_handler_, timeout_, context_));
+ }
+
+ void ssl_server::reinit_connection()
+@@ -305,7 +305,7 @@ void ssl_server::reinit_connection()
+ _log.Log(LOG_ERROR, "[web:%s] missing SSL DH parameters from file %s", settings_.listening_port.c_str(), settings_.tmp_dh_file_path.c_str());
+ }
+ }
+- new_connection_.reset(new connection(io_service_, connection_manager_, request_handler_, timeout_, context_));
++ new_connection_.reset(new connection(io_context_, connection_manager_, request_handler_, timeout_, context_));
+ }
+
+ /**
+diff --git webserver/server.hpp webserver/server.hpp
+index f9e71c5..bd7132a 100644
+--- webserver/server.hpp
++++ webserver/server.hpp
+@@ -31,7 +31,7 @@ namespace http
+ explicit server_base(const server_settings &settings, request_handler &user_request_handler);
+ virtual ~server_base() = default;
+
+- /// Run the server's io_service loop.
++ /// Run the server's io_context loop.
+ void run();
+
+ /// Stop the server.
+@@ -46,8 +46,8 @@ namespace http
+ protected:
+ void init(const init_connectionhandler_func &init_connection_handler, accept_handler_func accept_handler);
+
+- /// The io_service used to perform asynchronous operations.
+- boost::asio::io_service io_service_;
++ /// The io_context used to perform asynchronous operations.
++ boost::asio::io_context io_context_;
+
+ /// Acceptor used to listen for incoming connections.
+ boost::asio::ip::tcp::acceptor acceptor_;
diff --git a/www/domoticz/Makefile b/www/domoticz/Makefile
index 769b4d500821..51b10699d732 100644
--- a/www/domoticz/Makefile
+++ b/www/domoticz/Makefile
@@ -1,5 +1,6 @@
PORTNAME= domoticz
DISTVERSION= 2024.7
+PORTREVISION= 1
CATEGORIES= www
MAINTAINER= kiwi@FreeBSD.org
@@ -9,8 +10,6 @@ WWW= https://www.domoticz.com
LICENSE= GPLv3
LICENSE_FILE= ${WRKSRC}/License.txt
-BROKEN= fails to build with Boost>=1.87
-
LIB_DEPENDS= libcurl.so:ftp/curl \
libboost_system.so:devel/boost-libs \
libjsoncpp.so:devel/jsoncpp \
diff --git a/www/domoticz/files/patch-pr6252 b/www/domoticz/files/patch-pr6252
new file mode 100644
index 000000000000..34c4efd3f4e4
--- /dev/null
+++ b/www/domoticz/files/patch-pr6252
@@ -0,0 +1,2178 @@
+Fix for boost 1.87
+
+Removed the diff for the msbuild project files, didn't apply cleanly and not relevant anyway.
+This will merged in the next stable of domoticz.
+
+Pullrequest: https://github.com/domoticz/domoticz/pull/6252
+Patch: https://patch-diff.githubusercontent.com/raw/domoticz/domoticz/pull/6252.patch-diff
+
+diff --git hardware/ASyncSerial.cpp hardware/ASyncSerial.cpp
+index 52c950d..6147cdb 100644
+--- hardware/ASyncSerial.cpp
++++ hardware/ASyncSerial.cpp
+@@ -54,7 +54,7 @@ public:
+ {
+ }
+
+- boost::asio::io_service io; ///< Io service object
++ boost::asio::io_context io; ///< Io service object
+ boost::asio::serial_port port; ///< Serial port object
+ boost::thread backgroundThread; ///< Thread that runs read/write operations
+ bool open{ false }; ///< True if port open
+@@ -117,10 +117,10 @@ void AsyncSerial::open(const std::string& devname, unsigned int baud_rate,
+ throw;
+ }
+
+- pimpl->io.reset();
++ pimpl->io.restart();
+
+- // This gives some work to the io_service before it is started
+- pimpl->io.post([this] { return doRead(); });
++ // This gives some work to the io_context before it is started
++ boost::asio::post(pimpl->io, [this] { return doRead(); });
+
+ boost::thread t([p = &pimpl->io] { p->run(); });
+ pimpl->backgroundThread.swap(t);
+@@ -149,10 +149,10 @@ void AsyncSerial::openOnlyBaud(const std::string& devname, unsigned int baud_rat
+ throw;
+ }
+
+- pimpl->io.reset();
++ pimpl->io.restart();
+
+- //This gives some work to the io_service before it is started
+- pimpl->io.post([this] { return doRead(); });
++ //This gives some work to the io_context before it is started
++ boost::asio::post(pimpl->io, [this] { return doRead(); });
+
+ boost::thread t([p = &pimpl->io] { p->run(); });
+ pimpl->backgroundThread.swap(t);
+@@ -176,9 +176,9 @@ void AsyncSerial::close()
+ if(!isOpen()) return;
+
+ pimpl->open = false;
+- pimpl->io.post([this] { doClose(); });
++ boost::asio::post(pimpl->io, [this] { doClose(); });
+ pimpl->backgroundThread.join();
+- pimpl->io.reset();
++ pimpl->io.restart();
+ if(errorStatus())
+ {
+ throw(boost::system::system_error(boost::system::error_code(),
+@@ -192,7 +192,7 @@ void AsyncSerial::write(const char *data, size_t size)
+ std::lock_guard<std::mutex> l(pimpl->writeQueueMutex);
+ pimpl->writeQueue.insert(pimpl->writeQueue.end(),data,data+size);
+ }
+- pimpl->io.post([this] { doWrite(); });
++ boost::asio::post(pimpl->io, [this] { doWrite(); });
+ }
+
+ void AsyncSerial::write(const std::string &data)
+@@ -201,7 +201,7 @@ void AsyncSerial::write(const std::string &data)
+ std::lock_guard<std::mutex> l(pimpl->writeQueueMutex);
+ pimpl->writeQueue.insert(pimpl->writeQueue.end(), data.c_str(), data.c_str()+data.size());
+ }
+- pimpl->io.post([this] { doWrite(); });
++ boost::asio::post(pimpl->io, [this] { doWrite(); });
+ }
+
+ void AsyncSerial::write(const std::vector<char>& data)
+@@ -211,7 +211,7 @@ void AsyncSerial::write(const std::vector<char>& data)
+ pimpl->writeQueue.insert(pimpl->writeQueue.end(),data.begin(),
+ data.end());
+ }
+- pimpl->io.post([this] { doWrite(); });
++ boost::asio::post(pimpl->io, [this] { doWrite(); });
+ }
+
+ void AsyncSerial::writeString(const std::string& s)
+@@ -220,7 +220,7 @@ void AsyncSerial::writeString(const std::string& s)
+ std::lock_guard<std::mutex> l(pimpl->writeQueueMutex);
+ pimpl->writeQueue.insert(pimpl->writeQueue.end(),s.begin(),s.end());
+ }
+- pimpl->io.post([this] { doWrite(); });
++ boost::asio::post(pimpl->io, [this] { doWrite(); });
+ }
+
+ void AsyncSerial::doRead()
+diff --git hardware/ASyncSerial.h hardware/ASyncSerial.h
+index 0a51ef0..de83f8a 100644
+--- hardware/ASyncSerial.h
++++ hardware/ASyncSerial.h
+@@ -123,27 +123,27 @@ class AsyncSerial : private domoticz::noncopyable
+
+ /**
+ * Callback called to start an asynchronous read operation.
+- * This callback is called by the io_service in the spawned thread.
++ * This callback is called by the io_context in the spawned thread.
+ */
+ void doRead();
+
+ /**
+ * Callback called at the end of the asynchronous operation.
+- * This callback is called by the io_service in the spawned thread.
++ * This callback is called by the io_context in the spawned thread.
+ */
+ void readEnd(const boost::system::error_code &error, size_t bytes_transferred);
+
+ /**
+ * Callback called to start an asynchronous write operation.
+ * If it is already in progress, does nothing.
+- * This callback is called by the io_service in the spawned thread.
++ * This callback is called by the io_context in the spawned thread.
+ */
+ void doWrite();
+
+ /**
+ * Callback called at the end of an asynchronuous write operation,
+ * if there is more data to write, restarts a new write operation.
+- * This callback is called by the io_service in the spawned thread.
++ * This callback is called by the io_context in the spawned thread.
+ */
+ void writeEnd(const boost::system::error_code &error);
+
+diff --git hardware/ASyncTCP.cpp hardware/ASyncTCP.cpp
+index a375561..7c3b536 100644
+--- hardware/ASyncTCP.cpp
++++ hardware/ASyncTCP.cpp
+@@ -4,213 +4,241 @@
+ #include <boost/system/error_code.hpp> // for error_code
+ #include "../main/Logger.h"
+
+-struct hostent;
+-
+ #define MAX_TCP_BUFFER_SIZE 4096
+
+-#ifndef WIN32
+- #include <unistd.h> //gethostbyname
+-#endif
+-
+ #define STATUS_OK(err) !err
+-
+-ASyncTCP::ASyncTCP(const bool secure)
++#define STATUS_ERR(err) err
++
++ASyncTCP::ASyncTCP(const bool secure) :
++ m_Tcpwork(boost::asio::make_work_guard(m_io_context))
++ , m_Socket(m_io_context)
++ , m_Resolver(m_io_context)
++ , m_ReconnectTimer(m_io_context)
++ , m_TimeoutTimer(m_io_context)
++ , m_SendStrand(m_io_context)
+ #ifdef WWW_ENABLE_SSL
+- : mSecure(secure)
++ , m_bSecure(secure)
+ #endif
+ {
+ m_pRXBuffer = new uint8_t[MAX_TCP_BUFFER_SIZE];
+ #ifdef WWW_ENABLE_SSL
+ mContext.set_verify_mode(boost::asio::ssl::verify_none);
+- if (mSecure)
++ if (m_bSecure)
+ {
+- mSslSocket.reset(new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(mIos, mContext));
++ m_SslSocket.reset(new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(m_io_context, mContext));
+ }
+ #endif
+ }
+
+ ASyncTCP::~ASyncTCP()
+ {
+- assert(mTcpthread == nullptr);
+- mIsTerminating = true;
+- if (mTcpthread)
++ assert(m_Tcpthread == nullptr);
++ m_bIsTerminating = true;
++ if (m_Tcpthread)
+ {
+ //This should never happen. terminate() never called!!
+- _log.Log(LOG_ERROR, "ASyncTCP: Workerthread not closed. terminate() never called!!!");
+- mIos.stop();
+- if (mTcpthread)
++ _log.Log(LOG_ERROR, "ASyncTCP: Worker thread not closed. terminate() never called!!!");
++ m_io_context.stop();
++ if (m_Tcpthread)
+ {
+- mTcpthread->join();
+- mTcpthread.reset();
++ m_Tcpthread->join();
++ m_Tcpthread.reset();
+ }
+ }
+ if (m_pRXBuffer != nullptr)
+ delete[] m_pRXBuffer;
+ }
+
+-void ASyncTCP::SetReconnectDelay(int32_t Delay)
++void ASyncTCP::SetReconnectDelay(const int32_t Delay)
+ {
+- mReconnectDelay = Delay;
++ m_iReconnectDelay = Delay;
+ }
+
+ void ASyncTCP::connect(const std::string& ip, uint16_t port)
+ {
+- assert(!mSocket.is_open());
+- if (mSocket.is_open())
++ assert(!m_Socket.is_open());
++ if (m_Socket.is_open())
+ {
+ _log.Log(LOG_ERROR, "ASyncTCP: connect called while socket is still open. !!!");
+ terminate();
+ }
+
+- // RK: We reset mIos here because it might have been stopped in terminate()
+- mIos.reset();
+- // RK: After the reset, we need to provide it work anew
+- mTcpwork = std::make_shared<boost::asio::io_service::work>(mIos);
+- if (!mTcpthread)
+- mTcpthread = std::make_shared<std::thread>([p = &mIos] { p->run(); });
+-
+- mIp = ip;
+- mPort = port;
++ m_IP = ip;
++ m_Port = port;
+ std::string port_str = std::to_string(port);
+- boost::asio::ip::tcp::resolver::query query(ip, port_str);
+ timeout_start_timer();
+- mResolver.async_resolve(query, [this](auto &&err, auto &&iter) { cb_resolve_done(err, iter); });
++
++ m_Resolver.async_resolve(
++ ip, port_str,
++ [this](const boost::system::error_code& error, const boost::asio::ip::tcp::resolver::results_type& endpoints) {
++ handle_resolve(error, endpoints);
++ }
++ );
++
++ // RK: We restart m_io_context here because it might have been stopped in terminate()
++ m_io_context.restart();
++ // RK: After the reset, we need to provide it work anew
++ m_Tcpwork.reset();
++ m_Tcpwork.emplace(boost::asio::make_work_guard(m_io_context));
++ if (!m_Tcpthread)
++ m_Tcpthread = std::make_shared<std::thread>([p = &m_io_context] { p->run(); });
+ }
+
+-void ASyncTCP::cb_resolve_done(const boost::system::error_code& error, boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
++void ASyncTCP::handle_resolve(const boost::system::error_code& error, const boost::asio::ip::tcp::resolver::results_type &endpoints)
+ {
+- if (mIsTerminating) return;
++ if (m_bIsTerminating) return;
+
+- if (STATUS_OK(error))
+- {
+- connect_start(endpoint_iterator);
+- }
+- else
++ if (STATUS_ERR(error))
+ {
+ process_error(error);
++ return;
+ }
+-}
+-
+-void ASyncTCP::connect_start(boost::asio::ip::tcp::resolver::iterator& endpoint_iterator)
+-{
+- if (mIsConnected) return;
+-
+- mEndPoint = *endpoint_iterator++;
++ if (m_bIsConnected) return;
+
+ timeout_start_timer();
++
+ #ifdef WWW_ENABLE_SSL
+- if (mSecure)
++ if (m_bSecure)
+ {
+ // we reset the ssl socket, because the ssl context needs to be reinitialized after a reconnect
+- mSslSocket.reset(new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(mIos, mContext));
+- mSslSocket->lowest_layer().async_connect(mEndPoint, [this, endpoint_iterator](auto &&err) mutable { cb_connect_done(err, endpoint_iterator); });
++ m_SslSocket.reset(new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(m_io_context, mContext));
++ boost::asio::async_connect(m_SslSocket->lowest_layer(), endpoints,
++ [this](const boost::system::error_code& error, const boost::asio::ip::tcp::endpoint& endpoint)
++ {
++ handle_connect(error, endpoint);
++ }
++ );
+ }
+ else
+ #endif
+ {
+- mSocket.async_connect(mEndPoint, [this, endpoint_iterator](auto &&err) mutable { cb_connect_done(err, endpoint_iterator); });
++ boost::asio::async_connect(m_Socket, endpoints,
++ [this](const boost::system::error_code& error, const boost::asio::ip::tcp::endpoint& endpoint)
++ {
++ handle_connect(error, endpoint);
++ }
++ );
+ }
+ }
+
+-void ASyncTCP::cb_connect_done(const boost::system::error_code& error, boost::asio::ip::tcp::resolver::iterator &endpoint_iterator)
++void ASyncTCP::handle_connect(const boost::system::error_code& error, const boost::asio::ip::tcp::endpoint& /*endpoint*/)
+ {
+- if (mIsTerminating) return;
++ if (m_bIsTerminating) return;
+
+- if (STATUS_OK(error))
++ if (STATUS_ERR(error))
+ {
++ process_error(error);
++ return;
++ }
+ #ifdef WWW_ENABLE_SSL
+- if (mSecure)
+- {
+- timeout_start_timer();
+- mSslSocket->async_handshake(boost::asio::ssl::stream_base::client, [this](auto &&err) { cb_handshake_done(err); });
+- }
+- else
+-#endif
+- {
+- process_connection();
+- }
++ if (m_bSecure)
++ {
++ timeout_start_timer();
++ m_SslSocket->async_handshake(boost::asio::ssl::stream_base::client,
++ [this](const boost::system::error_code& error) {
++ cb_handshake_done(error);
++ }
++ );
+ }
+- else
++ else
++#endif
+ {
+- if (endpoint_iterator != boost::asio::ip::tcp::resolver::iterator())
+- {
+- // The connection failed. Try the next endpoint in the list.
+- connect_start(endpoint_iterator);
+- return;
+- }
+- process_error(error);
++ process_connection();
+ }
+ }
+
+ #ifdef WWW_ENABLE_SSL
+ void ASyncTCP::cb_handshake_done(const boost::system::error_code& error)
+ {
+- if (mIsTerminating) return;
++ if (m_bIsTerminating) return;
+
+- if (STATUS_OK(error))
+- {
+- process_connection();
+- }
+- else
++ if (STATUS_ERR(error))
+ {
+ process_error(error);
++ return;
+ }
++ process_connection();
++#endif
+ }
++
++void ASyncTCP::process_connection()
++{
++ m_bIsConnected = true;
++#ifdef WWW_ENABLE_SSL
++
++ if (!m_bSecure)
+ #endif
++ {
++ // RK: only if non-secure
++ boost::asio::socket_base::keep_alive option(true);
++ m_Socket.set_option(option);
++ }
++ OnConnect();
++ do_read_start();
++ do_write_start();
++}
+
+ void ASyncTCP::reconnect_start_timer()
+ {
+- if (mIsReconnecting) return;
++ if (m_bIsReconnecting) return;
+
+- if (mReconnectDelay != 0)
++ if (m_iReconnectDelay != 0)
+ {
+- mIsReconnecting = true;
+-
+- mReconnectTimer.expires_from_now(boost::posix_time::seconds(mReconnectDelay));
+- mReconnectTimer.async_wait([this](auto &&err) { cb_reconnect_start(err); });
++ m_bIsReconnecting = true;
++
++ m_ReconnectTimer.expires_from_now(boost::posix_time::seconds(m_iReconnectDelay));
++ m_ReconnectTimer.async_wait(
++ [this](const boost::system::error_code& error) {
++ cb_reconnect_start(error);
++ }
++ );
+ }
+ }
+
+ void ASyncTCP::cb_reconnect_start(const boost::system::error_code& error)
+ {
+- mIsReconnecting = false;
+- mReconnectTimer.cancel();
+- mTimeoutTimer.cancel();
++ m_bIsReconnecting = false;
++ m_ReconnectTimer.cancel();
++ m_TimeoutTimer.cancel();
+
+- if (mIsConnected) return;
++ if (m_bIsConnected) return;
+ if (error) return; // timer was cancelled
+
+ do_close();
+- connect(mIp, mPort);
++ connect(m_IP, m_Port);
+ }
+
+
+ void ASyncTCP::terminate(const bool silent)
+ {
+- mIsTerminating = true;
++ m_bIsTerminating = true;
+ disconnect(silent);
+- mTcpwork.reset();
+- mIos.stop();
+- if (mTcpthread)
++ m_Tcpwork.reset();
++ m_io_context.stop();
++ if (m_Tcpthread)
+ {
+- mTcpthread->join();
+- mTcpthread.reset();
++ m_Tcpthread->join();
++ m_Tcpthread.reset();
+ }
+- mIsReconnecting = false;
+- mIsConnected = false;
+- mWriteQ.clear();
+- mIsTerminating = false;
++ m_bIsReconnecting = false;
++ m_bIsConnected = false;
++ m_WriteQ.clear();
++ m_bIsTerminating = false;
+ }
+
+ void ASyncTCP::disconnect(const bool silent)
+ {
+- mReconnectTimer.cancel();
+- mTimeoutTimer.cancel();
+- if (!mTcpthread) return;
++ m_ReconnectTimer.cancel();
++ m_TimeoutTimer.cancel();
++ if (!m_Tcpthread) return;
+
+ try
+ {
+- mIos.post([this] { do_close(); });
++ boost::asio::post(m_io_context,
++ [this] {
++ do_close();
++ }
++ );
+ }
+ catch (...)
+ {
+@@ -223,62 +251,68 @@ void ASyncTCP::disconnect(const bool silent)
+
+ void ASyncTCP::do_close()
+ {
+- if (mIsReconnecting) {
++ if (m_bIsReconnecting) {
+ return;
+ }
+- mReconnectTimer.cancel();
+- mTimeoutTimer.cancel();
++ m_ReconnectTimer.cancel();
++ m_TimeoutTimer.cancel();
+ boost::system::error_code ec;
+ #ifdef WWW_ENABLE_SSL
+- if (mSecure)
++ if (m_bSecure)
+ {
+- if (mSslSocket->lowest_layer().is_open())
++ if (m_SslSocket->lowest_layer().is_open())
+ {
+- mSslSocket->lowest_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
+- mSslSocket->lowest_layer().close(ec);
++ m_SslSocket->lowest_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
++ m_SslSocket->lowest_layer().close(ec);
+ }
+ }
+ else
+ #endif
+ {
+- if (mSocket.is_open())
++ if (m_Socket.is_open())
+ {
+- mSocket.close(ec);
++ m_Socket.close(ec);
+ }
+ }
+ }
+
+ void ASyncTCP::do_read_start()
+ {
+- if (mIsTerminating) return;
+- if (!mIsConnected) return;
++ if (m_bIsTerminating) return;
++ if (!m_bIsConnected) return;
+
+ timeout_start_timer();
+ #ifdef WWW_ENABLE_SSL
+- if (mSecure)
++ if (m_bSecure)
+ {
+- mSslSocket->async_read_some(boost::asio::buffer(m_pRXBuffer, MAX_TCP_BUFFER_SIZE), [this](auto &&err, auto bytes) { cb_read_done(err, bytes); });
++ m_SslSocket->async_read_some(boost::asio::buffer(m_pRXBuffer, MAX_TCP_BUFFER_SIZE),
++ [this](const boost::system::error_code& error, size_t bytes_transferred) {
++ cb_read_done(error, bytes_transferred);
++ }
++ );
+ }
+ else
+ #endif
+ {
+- mSocket.async_read_some(boost::asio::buffer(m_pRXBuffer, MAX_TCP_BUFFER_SIZE), [this](auto &&err, auto bytes) { cb_read_done(err, bytes); });
++ m_Socket.async_read_some(boost::asio::buffer(m_pRXBuffer, MAX_TCP_BUFFER_SIZE),
++ [this](const boost::system::error_code& error, size_t bytes_transferred) {
++ cb_read_done(error, bytes_transferred);
++ }
++ );
+ }
+ }
+
+ void ASyncTCP::cb_read_done(const boost::system::error_code& error, size_t bytes_transferred)
+ {
+- if (mIsTerminating) return;
++ if (m_bIsTerminating) return;
+
+- if (STATUS_OK(error))
+- {
+- OnData(m_pRXBuffer, bytes_transferred);
+- do_read_start();
+- }
+- else
++ if (STATUS_ERR(error))
+ {
+ process_error(error);
++ return;
+ }
++ OnData(m_pRXBuffer, bytes_transferred);
++ do_read_start();
+ }
+
+ void ASyncTCP::write(const uint8_t* pData, size_t length)
+@@ -288,77 +322,66 @@ void ASyncTCP::write(const uint8_t* pData, size_t length)
+
+ void ASyncTCP::write(const std::string& msg)
+ {
+- if (!mTcpthread) return;
++ if (!m_Tcpthread) return;
+
+- mSendStrand.post([this, msg]() { cb_write_queue(msg); });
++ boost::asio::post(m_SendStrand, [this, msg]() { cb_write_queue(msg); });
+ }
+
+ void ASyncTCP::cb_write_queue(const std::string& msg)
+ {
+- mWriteQ.push_back(msg);
++ m_WriteQ.push_back(msg);
+
+- if (mWriteQ.size() == 1)
++ if (m_WriteQ.size() == 1)
+ do_write_start();
+ }
+
+ void ASyncTCP::do_write_start()
+ {
+- if (mIsTerminating) return;
+- if (!mIsConnected) return;
+- if (mWriteQ.empty())
++ if (m_bIsTerminating) return;
++ if (!m_bIsConnected) return;
++ if (m_WriteQ.empty())
+ return;
+
+ timeout_start_timer();
+ #ifdef WWW_ENABLE_SSL
+- if (mSecure)
++ if (m_bSecure)
+ {
+- boost::asio::async_write(*mSslSocket, boost::asio::buffer(mWriteQ.front()), [this](auto &&err, auto) { cb_write_done(err); });
++ boost::asio::async_write(*m_SslSocket, boost::asio::buffer(m_WriteQ.front()),
++ [this](const boost::system::error_code& error, std::size_t length) {
++ cb_write_done(error, length);
++ }
++ );
+ }
+ else
+ #endif
+ {
+- boost::asio::async_write(mSocket, boost::asio::buffer(mWriteQ.front()), [this](auto &&err, auto) { cb_write_done(err); });
++ boost::asio::async_write(m_Socket, boost::asio::buffer(m_WriteQ.front()),
++ [this](const boost::system::error_code& error, std::size_t length) {
++ cb_write_done(error, length);
++ }
++ );
+ }
+ }
+
+-void ASyncTCP::cb_write_done(const boost::system::error_code& error)
++void ASyncTCP::cb_write_done(const boost::system::error_code& error, std::size_t /*length*/)
+ {
+- if (mIsTerminating) return;
++ if (m_bIsTerminating) return;
+
+- if (STATUS_OK(error))
+- {
+- mWriteQ.pop_front();
+- do_write_start();
+- }
+- else
++ if (STATUS_ERR(error))
+ {
+ process_error(error);
++ return;
+ }
+-}
+-
+-void ASyncTCP::process_connection()
+-{
+- mIsConnected = true;
+-#ifdef WWW_ENABLE_SSL
+-
+- if (!mSecure)
+-#endif
+- {
+- // RK: only if non-secure
+- boost::asio::socket_base::keep_alive option(true);
+- mSocket.set_option(option);
+- }
+- OnConnect();
+- do_read_start();
++ m_WriteQ.pop_front();
+ do_write_start();
+ }
+
+ void ASyncTCP::process_error(const boost::system::error_code& error)
+ {
+ do_close();
+- if (mIsConnected)
++ if (m_bIsConnected)
+ {
+- mIsConnected = false;
++ m_bIsConnected = false;
+ OnDisconnect();
+ }
+
+@@ -369,20 +392,23 @@ void ASyncTCP::process_error(const boost::system::error_code& error)
+ reconnect_start_timer();
+ }
+
+-/* timeout methods */
+ void ASyncTCP::timeout_start_timer()
+ {
+- if (0 == mTimeoutDelay) {
++ if (0 == m_iTimeoutDelay) {
+ return;
+ }
+ timeout_cancel_timer();
+- mTimeoutTimer.expires_from_now(boost::posix_time::seconds(mTimeoutDelay));
+- mTimeoutTimer.async_wait([this](auto &&err) { timeout_handler(err); });
++ m_TimeoutTimer.expires_from_now(boost::posix_time::seconds(m_iTimeoutDelay));
++ m_TimeoutTimer.async_wait(
++ [this](const boost::system::error_code& error) {
++ timeout_handler(error);
++ }
++ );
+ }
+
+ void ASyncTCP::timeout_cancel_timer()
+ {
+- mTimeoutTimer.cancel();
++ m_TimeoutTimer.cancel();
+ }
+
+ void ASyncTCP::timeout_handler(const boost::system::error_code& error)
+@@ -397,5 +423,5 @@ void ASyncTCP::timeout_handler(const boost::system::error_code& error)
+
+ void ASyncTCP::SetTimeout(const uint32_t Timeout)
+ {
+- mTimeoutDelay = Timeout;
++ m_iTimeoutDelay = Timeout;
+ }
+diff --git hardware/ASyncTCP.h hardware/ASyncTCP.h
+index cf859bb..a8b3ae2 100644
+--- hardware/ASyncTCP.h
++++ hardware/ASyncTCP.h
+@@ -3,39 +3,31 @@
+ #include <stddef.h> // for size_t
+ #include <deque> // for write queue
+ #include <boost/asio/deadline_timer.hpp> // for deadline_timer
+-#include <boost/asio/io_service.hpp> // for io_service
++#include <boost/asio/io_context.hpp> // for io_context
+ #include <boost/asio/strand.hpp> // for strand
+ #include <boost/asio/ip/tcp.hpp> // for tcp, tcp::endpoint, tcp::s...
+ #include <boost/asio/ssl.hpp> // for secure sockets
+ #include <boost/asio/ssl/stream.hpp> // for secure sockets
+ #include <exception> // for exception
++#include <optional> // for optional
+
+ #define ASYNCTCP_THREAD_NAME "ASyncTCP"
+ #define DEFAULT_RECONNECT_TIME 30
+ #define DEFAULT_TIMEOUT_TIME 60
+
+-namespace boost
+-{
+- namespace system
+- {
+- class error_code;
+- } // namespace system
+-} // namespace boost
+-
+ class ASyncTCP
+ {
+- protected:
++protected:
+ ASyncTCP(bool secure = false);
+ virtual ~ASyncTCP();
+-
+- void connect(const std::string &hostname, uint16_t port);
++ void connect(const std::string& hostname, uint16_t port);
+ void disconnect(bool silent = true);
+- void write(const std::string &msg);
+- void write(const uint8_t *pData, size_t length);
+- void SetReconnectDelay(int32_t Delay = DEFAULT_RECONNECT_TIME);
++ void write(const std::string& msg);
++ void write(const uint8_t* pData, size_t length);
++ void SetReconnectDelay(const int32_t Delay = DEFAULT_RECONNECT_TIME);
+ bool isConnected()
+ {
+- return mIsConnected;
++ return m_bIsConnected;
+ };
+ void terminate(bool silent = true);
+ void SetTimeout(uint32_t Timeout = DEFAULT_TIMEOUT_TIME);
+@@ -43,65 +35,61 @@ class ASyncTCP
+ // Callback interface to implement in derived classes
+ virtual void OnConnect() = 0;
+ virtual void OnDisconnect() = 0;
+- virtual void OnData(const uint8_t *pData, size_t length) = 0;
+- virtual void OnError(const boost::system::error_code &error) = 0;
+-
+- boost::asio::io_service mIos; // protected to allow derived classes to attach timers etc.
++ virtual void OnData(const uint8_t* pData, size_t length) = 0;
++ virtual void OnError(const boost::system::error_code& error) = 0;
+
+- private:
+- void cb_resolve_done(const boost::system::error_code &err, boost::asio::ip::tcp::resolver::iterator endpoint_iterator);
+- void connect_start(boost::asio::ip::tcp::resolver::iterator &endpoint_iterator);
+- void cb_connect_done(const boost::system::error_code &error, boost::asio::ip::tcp::resolver::iterator &endpoint_iterator);
++ boost::asio::io_context m_io_context; // protected to allow derived classes to attach timers etc.
++private:
++ void handle_resolve(const boost::system::error_code& ec, const boost::asio::ip::tcp::resolver::results_type &results);
++ void handle_connect(const boost::system::error_code& error, const boost::asio::ip::tcp::endpoint& endpoint);
+ #ifdef WWW_ENABLE_SSL
+- void cb_handshake_done(const boost::system::error_code &error);
++ void cb_handshake_done(const boost::system::error_code& error);
+ #endif
+
+- /* timeout methods */
+ void timeout_start_timer();
+ void timeout_cancel_timer();
+ void reconnect_start_timer();
+- void timeout_handler(const boost::system::error_code &error);
++ void timeout_handler(const boost::system::error_code& error);
+
+- void cb_reconnect_start(const boost::system::error_code &error);
++ void cb_reconnect_start(const boost::system::error_code& error);
+
+ void do_close();
+
+ void do_read_start();
+- void cb_read_done(const boost::system::error_code &error, size_t bytes_transferred);
++ void cb_read_done(const boost::system::error_code& error, size_t bytes_transferred);
+
+- void cb_write_queue(const std::string &msg);
++ void cb_write_queue(const std::string& msg);
+ void do_write_start();
+- void cb_write_done(const boost::system::error_code &error);
++ void cb_write_done(const boost::system::error_code& error, size_t length);
+
+ void process_connection();
+- void process_error(const boost::system::error_code &error);
++ void process_error(const boost::system::error_code& error);
+
+- bool mIsConnected = false;
+- bool mIsReconnecting = false;
+- bool mIsTerminating = false;
++ bool m_bIsConnected = false;
++ bool m_bIsReconnecting = false;
++ bool m_bIsTerminating = false;
+
+- boost::asio::io_service::strand mSendStrand{ mIos };
+- std::deque<std::string> mWriteQ; // we need a write queue to allow concurrent writes
++ boost::asio::io_context::strand m_SendStrand;
++ std::deque<std::string> m_WriteQ; // we need a write queue to allow concurrent writes
+
+ uint8_t* m_pRXBuffer = nullptr;
+
+- int mReconnectDelay = DEFAULT_RECONNECT_TIME;
+- int mTimeoutDelay = 0;
+- boost::asio::deadline_timer mReconnectTimer{ mIos };
+- boost::asio::deadline_timer mTimeoutTimer{ mIos };
++ int m_iReconnectDelay = DEFAULT_RECONNECT_TIME;
++ int m_iTimeoutDelay = 0;
++ boost::asio::deadline_timer m_ReconnectTimer;
++ boost::asio::deadline_timer m_TimeoutTimer;
+
+- std::shared_ptr<std::thread> mTcpthread;
+- std::shared_ptr<boost::asio::io_service::work> mTcpwork;
++ std::shared_ptr<std::thread> m_Tcpthread;
++ std::optional<boost::asio::executor_work_guard<boost::asio::io_context::executor_type>> m_Tcpwork;
+
+ #ifdef WWW_ENABLE_SSL
+- const bool mSecure;
++ const bool m_bSecure;
+ boost::asio::ssl::context mContext{ boost::asio::ssl::context::sslv23 };
+- std::shared_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> mSslSocket; // the ssl socket
++ std::shared_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> m_SslSocket;
+ #endif
+- boost::asio::ip::tcp::socket mSocket{ mIos };
+- boost::asio::ip::tcp::endpoint mEndPoint;
+- boost::asio::ip::tcp::resolver mResolver{ mIos };
++ boost::asio::ip::tcp::socket m_Socket;
++ boost::asio::ip::tcp::resolver m_Resolver;
+
+- std::string mIp;
+- uint16_t mPort;
++ std::string m_IP;
++ uint16_t m_Port;
+ };
+diff --git hardware/Arilux.cpp hardware/Arilux.cpp
+index 400f5a3..20bc373 100644
+--- hardware/Arilux.cpp
++++ hardware/Arilux.cpp
+@@ -79,7 +79,7 @@ void Arilux::InsertUpdateSwitch(const std::string &lightName, const int subType,
+ {
+ uint32_t sID;
+ try {
+- sID = boost::asio::ip::address_v4::from_string(location).to_ulong();
++ sID = boost::asio::ip::make_address_v4(location).to_uint();
+ } catch (const std::exception &e) {
+ Log(LOG_ERROR, "Bad IP address: %s (%s)", location.c_str(), e.what());
+ return;
+@@ -112,8 +112,8 @@ bool Arilux::SendTCPCommand(uint32_t ip,std::vector<unsigned char> &command)
+ sum = sum & 0xFF;
+ command.push_back((unsigned char)sum);
+
+- boost::asio::io_service io_service;
+- boost::asio::ip::tcp::socket sendSocket(io_service);
++ boost::asio::io_context io_context;
++ boost::asio::ip::tcp::socket sendSocket(io_context);
+ boost::asio::ip::address_v4 address(ip);
+ boost::asio::ip::tcp::endpoint endpoint(address, 5577);
+ try
+diff --git hardware/Kodi.cpp hardware/Kodi.cpp
+index b528017..5ababf6 100644
+--- hardware/Kodi.cpp
++++ hardware/Kodi.cpp
+@@ -143,14 +143,14 @@ _eNotificationTypes CKodiNode::CKodiStatus::NotificationType()
+ }
+ }
+
+-CKodiNode::CKodiNode(boost::asio::io_service *pIos, const int pHwdID, const int PollIntervalsec, const int pTimeoutMs,
++CKodiNode::CKodiNode(boost::asio::io_context *pIoc, const int pHwdID, const int PollIntervalsec, const int pTimeoutMs,
+ const std::string& pID, const std::string& pName, const std::string& pIP, const std::string& pPort)
+ {
+ m_Busy = false;
+ m_Stoppable = false;
+ m_PlaylistPosition = 0;
+
+- m_Ios = pIos;
++ m_Ioc = pIoc;
+ m_HwdID = pHwdID;
+ m_DevID = atoi(pID.c_str());
+ sprintf(m_szDevID, "%X%02X%02X%02X", 0, 0, (m_DevID & 0xFF00) >> 8, m_DevID & 0xFF);
+@@ -581,11 +581,10 @@ void CKodiNode::handleConnect()
+ {
+ m_iMissedPongs = 0;
+ boost::system::error_code ec;
+- boost::asio::ip::tcp::resolver resolver(*m_Ios);
+- boost::asio::ip::tcp::resolver::query query(m_IP, (m_Port[0] != '-' ? m_Port : m_Port.substr(1)));
+- auto iter = resolver.resolve(query);
+- boost::asio::ip::tcp::endpoint endpoint = *iter;
+- m_Socket = new boost::asio::ip::tcp::socket(*m_Ios);
++ boost::asio::ip::tcp::resolver resolver(*m_Ioc);
++ auto iter = resolver.resolve(m_IP, (m_Port[0] != '-' ? m_Port : m_Port.substr(1)));
++ boost::asio::ip::tcp::endpoint endpoint = *iter.begin();
++ m_Socket = new boost::asio::ip::tcp::socket(*m_Ioc);
+ m_Socket->connect(endpoint, ec);
+ if (!ec)
+ {
+@@ -975,19 +974,19 @@ void CKodi::Do_Work()
+ _log.Log(LOG_NORM, "Kodi: (%s) - Restarting thread.", node->m_Name.c_str());
+ boost::thread *tAsync = new boost::thread(&CKodiNode::Do_Work, node);
+ SetThreadName(tAsync->native_handle(), "KodiNode");
+- m_ios.stop();
++ m_ioc.stop();
+ }
+ if (node->IsOn())
+ bWorkToDo = true;
+ }
+
+- if (bWorkToDo && m_ios.stopped()) // make sure that there is a boost thread to service i/o operations
++ if (bWorkToDo && m_ioc.stopped()) // make sure that there is a boost thread to service i/o operations
+ {
+- m_ios.reset();
++ m_ioc.restart();
+ // Note that this is the only thread that handles async i/o so we don't
+ // need to worry about locking or concurrency issues when processing messages
+ _log.Log(LOG_NORM, "Kodi: Restarting I/O service thread.");
+- boost::thread bt([p = &m_ios] { p->run(); });
++ boost::thread bt([p = &m_ioc] { p->run(); });
+ SetThreadName(bt.native_handle(), "KodiIO");
+ }
+ }
+@@ -1138,7 +1137,7 @@ void CKodi::ReloadNodes()
+ {
+ UnloadNodes();
+
+- m_ios.reset(); // in case this is not the first time in
++ m_ioc.restart(); // in case this is not the first time in
+
+ std::vector<std::vector<std::string> > result;
+ result = m_sql.safe_query("SELECT ID,Name,MacAddress,Timeout FROM WOLNodes WHERE (HardwareID==%d)", m_HwdID);
+@@ -1149,7 +1148,7 @@ void CKodi::ReloadNodes()
+ // create a vector to hold the nodes
+ for (const auto &sd : result)
+ {
+- auto pNode = std::make_shared<CKodiNode>(&m_ios, m_HwdID, m_iPollInterval, m_iPingTimeoutms, sd[0], sd[1], sd[2], sd[3]);
++ auto pNode = std::make_shared<CKodiNode>(&m_ioc, m_HwdID, m_iPollInterval, m_iPingTimeoutms, sd[0], sd[1], sd[2], sd[3]);
+ m_pNodes.push_back(pNode);
+ }
+ // start the threads to control each kodi
+@@ -1161,7 +1160,7 @@ void CKodi::ReloadNodes()
+ }
+ sleep_milliseconds(100);
+ _log.Log(LOG_NORM, "Kodi: Starting I/O service thread.");
+- boost::thread bt([p = &m_ios] { p->run(); });
++ boost::thread bt([p = &m_ioc] { p->run(); });
+ SetThreadName(bt.native_handle(), "KodiIO");
+ }
+ }
+@@ -1170,10 +1169,10 @@ void CKodi::UnloadNodes()
+ {
+ std::lock_guard<std::mutex> l(m_mutex);
+
+- m_ios.stop(); // stop the service if it is running
++ m_ioc.stop(); // stop the service if it is running
+ sleep_milliseconds(100);
+
+- while (((!m_pNodes.empty()) || (!m_ios.stopped())))
++ while (((!m_pNodes.empty()) || (!m_ioc.stopped())))
+ {
+ for (auto itt = m_pNodes.begin(); itt != m_pNodes.end(); ++itt)
+ {
+diff --git hardware/Kodi.h hardware/Kodi.h
+index 14f331c..4435740 100644
+--- hardware/Kodi.h
++++ hardware/Kodi.h
+@@ -150,7 +150,7 @@ class CKodiNode : public std::enable_shared_from_this<CKodiNode>, StoppableTask
+ };
+
+ public:
+- CKodiNode(boost::asio::io_service *, int, int, int, const std::string &, const std::string &, const std::string &, const std::string &);
++ CKodiNode(boost::asio::io_context *, int, int, int, const std::string &, const std::string &, const std::string &, const std::string &);
+ ~CKodiNode();
+ void Do_Work();
+ void SendCommand(const std::string &);
+@@ -207,7 +207,7 @@ class CKodiNode : public std::enable_shared_from_this<CKodiNode>, StoppableTask
+ int m_iPollIntSec;
+ int m_iMissedPongs;
+ std::string m_sLastMessage;
+- boost::asio::io_service *m_Ios;
++ boost::asio::io_context *m_Ioc;
+ boost::asio::ip::tcp::socket *m_Socket;
+ std::array<char, 256> m_Buffer;
+ };
+@@ -243,5 +243,5 @@ class CKodi : public CDomoticzHardwareBase
+ int m_iPingTimeoutms;
+ std::shared_ptr<std::thread> m_thread;
+ std::mutex m_mutex;
+- boost::asio::io_service m_ios;
++ boost::asio::io_context m_ioc;
+ };
+diff --git hardware/MQTTAutoDiscover.h hardware/MQTTAutoDiscover.h
+index 0832664..1501d6f 100644
+--- hardware/MQTTAutoDiscover.h
++++ hardware/MQTTAutoDiscover.h
+@@ -176,7 +176,7 @@ public:
+ void on_message(const struct mosquitto_message *message) override;
+ void on_connect(int rc) override;
+ void on_disconnect(int rc) override;
+- void on_going_down();
++ void on_going_down() override;
+ private:
+ void InsertUpdateSwitch(_tMQTTASensor* pSensor);
+
+diff --git hardware/PanasonicTV.cpp hardware/PanasonicTV.cpp
+index fc57d34..ce20565 100644
+--- hardware/PanasonicTV.cpp
++++ hardware/PanasonicTV.cpp
+@@ -356,18 +356,17 @@ std::string CPanasonicNode::handleWriteAndRead(const std::string& pMessageToSend
+ {
+
+ _log.Debug(DEBUG_HARDWARE, "Panasonic Plugin: (%s) Handling message: '%s'.", m_Name.c_str(), pMessageToSend.c_str());
+- boost::asio::io_service io_service;
++ boost::asio::io_context io_context;
+ // Get a list of endpoints corresponding to the server name.
+- boost::asio::ip::tcp::resolver resolver(io_service);
+- boost::asio::ip::tcp::resolver::query query(m_IP, (m_Port[0] != '-' ? m_Port : m_Port.substr(1)));
+- auto iter = resolver.resolve(query);
++ boost::asio::ip::tcp::resolver resolver(io_context);
++ auto endpoints = resolver.resolve(m_IP, (m_Port[0] != '-' ? m_Port : m_Port.substr(1)));
++ auto iter = endpoints.begin();
+ boost::asio::ip::tcp::endpoint endpoint = *iter;
+- boost::asio::ip::tcp::resolver::iterator end;
+
+ // Try each endpoint until we successfully establish a connection.
+- boost::asio::ip::tcp::socket socket(io_service);
++ boost::asio::ip::tcp::socket socket(io_context);
+ boost::system::error_code error = boost::asio::error::host_not_found;
+- while (error && iter != end)
++ while (error && iter != endpoints.end())
+ {
+ socket.close();
+ if (handleConnect(socket, *iter, error))
+@@ -1060,7 +1059,7 @@ void CPanasonic::ReloadNodes()
+ {
+ UnloadNodes();
+
+- //m_ios.reset(); // in case this is not the first time in
++ //m_ioc.reset(); // in case this is not the first time in
+
+ std::vector<std::vector<std::string> > result;
+ result = m_sql.safe_query("SELECT ID,Name,MacAddress,Timeout FROM WOLNodes WHERE (HardwareID==%d)", m_HwdID);
+@@ -1088,10 +1087,10 @@ void CPanasonic::UnloadNodes()
+ {
+ std::lock_guard<std::mutex> l(m_mutex);
+
+- m_ios.stop(); // stop the service if it is running
++ m_ioc.stop(); // stop the service if it is running
+ sleep_milliseconds(100);
+
+- while (((!m_pNodes.empty()) || (!m_ios.stopped())))
++ while (((!m_pNodes.empty()) || (!m_ioc.stopped())))
+ {
+ for (auto itt = m_pNodes.begin(); itt != m_pNodes.end(); ++itt)
+ {
+diff --git hardware/PanasonicTV.h hardware/PanasonicTV.h
+index b0a94ff..30e1ca1 100644
+--- hardware/PanasonicTV.h
++++ hardware/PanasonicTV.h
+@@ -39,7 +39,7 @@ class CPanasonic : public CDomoticzHardwareBase
+ bool m_bTryIfOff;
+ std::shared_ptr<std::thread> m_thread;
+ std::mutex m_mutex;
+- boost::asio::io_service m_ios;
++ boost::asio::io_context m_ioc;
+
+ friend class CPanasonicNode;
+ };
+diff --git hardware/Pinger.cpp hardware/Pinger.cpp
+index a66c7a1..e070b29 100644
+--- hardware/Pinger.cpp
++++ hardware/Pinger.cpp
+@@ -21,23 +21,23 @@
+ #if BOOST_VERSION >= 107000
+ #define GET_IO_SERVICE(s) ((boost::asio::io_context&)(s).get_executor().context())
+ #else
+-#define GET_IO_SERVICE(s) ((s).get_io_service())
++#define GET_IO_SERVICE(s) ((s).get_io_context())
+ #endif
+
+ class pinger
+ : private domoticz::noncopyable
+ {
+ public:
+- pinger(boost::asio::io_service &io_service, const char *destination, const int iPingTimeoutms)
++ pinger(boost::asio::io_context &io_context, const char *destination, const int iPingTimeoutms)
+ : num_replies_(0)
+ , m_PingState(false)
+- , resolver_(io_service)
+- , socket_(io_service, boost::asio::ip::icmp::v4())
+- , timer_(io_service)
++ , resolver_(io_context)
++ , socket_(io_context, boost::asio::ip::icmp::v4())
++ , timer_(io_context)
+ , sequence_number_(0)
+ {
+- boost::asio::ip::icmp::resolver::query query(boost::asio::ip::icmp::v4(), destination, "");
+- destination_ = *resolver_.resolve(query);
++ auto endpoints = resolver_.resolve(boost::asio::ip::icmp::v4(), destination, "");
++ destination_ = endpoints.begin()->endpoint();
+
+ num_tries_ = 1;
+ PingTimeoutms_ = iPingTimeoutms;
+@@ -332,11 +332,11 @@ void CPinger::ReloadNodes()
+ void CPinger::Do_Ping_Worker(const PingNode &Node)
+ {
+ bool bPingOK = false;
+- boost::asio::io_service io_service;
++ boost::asio::io_context io_context;
+ try
+ {
+- pinger p(io_service, Node.IP.c_str(), m_iPingTimeoutms);
+- io_service.run();
++ pinger p(io_context, Node.IP.c_str(), m_iPingTimeoutms);
++ io_context.run();
+ if (p.m_PingState == true)
+ {
+ bPingOK = true;
+diff --git hardware/RFLinkMQTT.h hardware/RFLinkMQTT.h
+index e938328..72433b8 100644
+--- hardware/RFLinkMQTT.h
++++ hardware/RFLinkMQTT.h
+@@ -46,7 +46,7 @@ protected:
+ boost::signals2::connection m_sDeviceReceivedConnection;
+ boost::signals2::connection m_sSwitchSceneConnection;
+ void selectNextIPAdress( void );
+- virtual bool WriteInt(const std::string &sendString); // override;
++ bool WriteInt(const std::string &sendString) override;
+ void Do_Work();
+ virtual void SendHeartbeat();
+ void StopMQTT();
+diff --git hardware/TCPProxy/tcpproxy_server.cpp hardware/TCPProxy/tcpproxy_server.cpp
+index 8aceb0b..d77d4bf 100644
+--- hardware/TCPProxy/tcpproxy_server.cpp
++++ hardware/TCPProxy/tcpproxy_server.cpp
+@@ -18,12 +18,12 @@
+ #if BOOST_VERSION >= 107000
+ #define GET_IO_SERVICE(s) ((boost::asio::io_context&)(s).get_executor().context())
+ #else
+-#define GET_IO_SERVICE(s) ((s).get_io_service())
++#define GET_IO_SERVICE(s) ((s).get_io_context())
+ #endif
+
+ namespace tcp_proxy
+ {
+- bridge::bridge(boost::asio::io_service& ios)
++ bridge::bridge(boost::asio::io_context& ios)
+ : downstream_socket_(ios),
+ upstream_socket_(ios)
+ {
+@@ -44,7 +44,7 @@ namespace tcp_proxy
+ boost::asio::ip::tcp::endpoint end;
+
+
+- boost::asio::io_service &ios= GET_IO_SERVICE(downstream_socket_);
++ boost::asio::io_context &ios= GET_IO_SERVICE(downstream_socket_);
+ boost::asio::ip::tcp::resolver resolver(ios);
+ boost::asio::ip::tcp::resolver::query query(upstream_host, upstream_port, boost::asio::ip::resolver_query_base::numeric_service);
+ auto i = resolver.resolve(query);
+@@ -137,10 +137,10 @@ namespace tcp_proxy
+ }
+ //Acceptor Class
+ acceptor::acceptor(const std::string &local_host, unsigned short local_port, const std::string &upstream_host, const std::string &upstream_port)
+- : io_service_()
++ : io_context_()
+ , m_bDoStop(false)
+ , localhost_address(boost::asio::ip::address_v4::from_string(local_host))
+- , acceptor_(io_service_, boost::asio::ip::tcp::endpoint(localhost_address, local_port))
++ , acceptor_(io_context_, boost::asio::ip::tcp::endpoint(localhost_address, local_port))
+ , upstream_host_(upstream_host)
+ , upstream_port_(upstream_port)
+ {
+@@ -151,7 +151,7 @@ namespace tcp_proxy
+ {
+ try
+ {
+- session_ = std::make_shared<bridge>(io_service_);
++ session_ = std::make_shared<bridge>(io_context_);
+ session_->sDownstreamData.connect([this](auto d, auto l) { OnDownstreamData(d, l); });
+ session_->sUpstreamData.connect([this](auto d, auto l) { OnUpstreamData(d, l); });
+
+@@ -169,11 +169,11 @@ namespace tcp_proxy
+ m_bDoStop=false;
+
+ accept_connections();
+- // The io_service::run() call will block until all asynchronous operations
++ // The io_context::run() call will block until all asynchronous operations
+ // have finished. While the server is running, there is always at least one
+ // asynchronous operation outstanding: the asynchronous accept call waiting
+ // for new incoming connections.
+- io_service_.run();
++ io_context_.run();
+ return true;
+ }
+ bool acceptor::stop()
+@@ -181,14 +181,14 @@ namespace tcp_proxy
+ m_bDoStop=true;
+ // Post a call to the stop function so that server::stop() is safe to call
+ // from any thread.
+- io_service_.post([this] { handle_stop(); });
++ io_context_.post([this] { handle_stop(); });
+ return true;
+ }
+
+ void acceptor::handle_stop()
+ {
+ // The server is stopped by canceling all outstanding asynchronous
+- // operations. Once all operations have finished the io_service::run() call
++ // operations. Once all operations have finished the io_context::run() call
+ // will exit.
+ acceptor_.close();
+ //connection_manager_.stop_all();
+diff --git hardware/TCPProxy/tcpproxy_server.h hardware/TCPProxy/tcpproxy_server.h
+index 3d1a150..148e65f 100644
+--- hardware/TCPProxy/tcpproxy_server.h
++++ hardware/TCPProxy/tcpproxy_server.h
+@@ -10,7 +10,7 @@ namespace tcp_proxy
+ class bridge : public std::enable_shared_from_this<bridge>
+ {
+ public:
+- explicit bridge(boost::asio::io_service& ios);
++ explicit bridge(boost::asio::io_context& ios);
+ boost::asio::ip::tcp::socket& downstream_socket();
+ boost::asio::ip::tcp::socket& upstream_socket();
+
+@@ -52,8 +52,8 @@ namespace tcp_proxy
+ void OnUpstreamData(const unsigned char *pData, size_t Len);
+ void OnDownstreamData(const unsigned char *pData, size_t Len);
+
+- /// The io_service used to perform asynchronous operations.
+- boost::asio::io_service io_service_;
++ /// The io_context used to perform asynchronous operations.
++ boost::asio::io_context io_context_;
+ bool m_bDoStop;
+ boost::asio::ip::address_v4 localhost_address;
+ boost::asio::ip::tcp::acceptor acceptor_;
+diff --git hardware/XiaomiDeviceSupport.h hardware/XiaomiDeviceSupport.h
+index fad7884..4a76d96 100644
+--- hardware/XiaomiDeviceSupport.h
++++ hardware/XiaomiDeviceSupport.h
+@@ -15,6 +15,7 @@
+ class XiaomiDeviceSupport
+ {
+ public:
++ virtual ~XiaomiDeviceSupport() = default;
+ /**
+ * Method to get 'model' corresponding to the ID of the device in case the Gateway API didn't provide it.
+ *
+diff --git hardware/XiaomiGateway.cpp hardware/XiaomiGateway.cpp
+index 66acdc5..fb4387a 100644
+--- hardware/XiaomiGateway.cpp
++++ hardware/XiaomiGateway.cpp
+@@ -538,12 +538,12 @@ bool XiaomiGateway::SendMessageToGateway(const std::string &controlmessage)
+ {
+ std::string message = controlmessage;
+ bool result = true;
+- boost::asio::io_service io_service;
+- boost::asio::ip::udp::socket socket_(io_service, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0));
++ boost::asio::io_context io_context;
++ boost::asio::ip::udp::socket socket_(io_context, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0));
+ stdreplace(message, "@gatewaykey", GetGatewayKey());
+ std::shared_ptr<std::string> message1(new std::string(message));
+ boost::asio::ip::udp::endpoint remote_endpoint_;
+- remote_endpoint_ = boost::asio::ip::udp::endpoint(boost::asio::ip::address::from_string(m_GatewayIp), 9898);
++ remote_endpoint_ = boost::asio::ip::udp::endpoint(boost::asio::ip::make_address_v4(m_GatewayIp), 9898);
+ socket_.send_to(boost::asio::buffer(*message1), remote_endpoint_);
+ sleep_milliseconds(150); // TODO: reduce or remove sleep
+ std::array<char, 512> recv_buffer_;
+@@ -1015,15 +1015,14 @@ bool XiaomiGateway::StopHardware()
+ void XiaomiGateway::Do_Work()
+ {
+ Log(LOG_STATUS, "XiaomiGateway (ID=%d): Worker started...", m_HwdID);
+- boost::asio::io_service io_service;
++ boost::asio::io_context io_context;
+ // Find the local ip address that is similar to the xiaomi gateway
+ try
+ {
+- boost::asio::ip::udp::resolver resolver(io_service);
+- boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), m_GatewayIp, "");
+- auto endpoints = resolver.resolve(query);
+- boost::asio::ip::udp::endpoint ep = *endpoints;
+- boost::asio::ip::udp::socket socket(io_service);
++ boost::asio::ip::udp::resolver resolver(io_context);
++ auto endpoints = resolver.resolve(boost::asio::ip::udp::v4(), m_GatewayIp, "");
++ boost::asio::ip::udp::endpoint ep = *endpoints.begin();
++ boost::asio::ip::udp::socket socket(io_context);
+ socket.connect(ep);
+ boost::asio::ip::address addr = socket.local_endpoint().address();
+ std::string compareIp = m_GatewayIp.substr(0, (m_GatewayIp.length() - 3));
+@@ -1073,11 +1072,11 @@ void XiaomiGateway::Do_Work()
+ }
+ }
+
+- XiaomiGateway::xiaomi_udp_server udp_server(io_service, m_HwdID, m_GatewayIp, m_LocalIp, m_ListenPort9898, m_OutputMessage, m_IncludeVoltage, this);
++ XiaomiGateway::xiaomi_udp_server udp_server(io_context, m_HwdID, m_GatewayIp, m_LocalIp, m_ListenPort9898, m_OutputMessage, m_IncludeVoltage, this);
+ boost::thread bt;
+ if (m_ListenPort9898)
+ {
+- bt = boost::thread([p = &io_service] { p->run(); });
++ bt = boost::thread([p = &io_context] { p->run(); });
+ SetThreadName(bt.native_handle(), "XiaomiGatewayIO");
+ }
+
+@@ -1094,7 +1093,7 @@ void XiaomiGateway::Do_Work()
+ // Log(LOG_STATUS, "sec_counter %d", sec_counter);
+ }
+ }
+- io_service.stop();
++ io_context.stop();
+ if (bt.joinable())
+ {
+ bt.join();
+@@ -1178,9 +1177,9 @@ unsigned int XiaomiGateway::GetShortID(const std::string &nodeid)
+ return sID;
+ }
+
+-XiaomiGateway::xiaomi_udp_server::xiaomi_udp_server(boost::asio::io_service &io_service, int m_HwdID, const std::string &gatewayIp, const std::string &localIp, const bool listenPort9898,
++XiaomiGateway::xiaomi_udp_server::xiaomi_udp_server(boost::asio::io_context &io_context, int m_HwdID, const std::string &gatewayIp, const std::string &localIp, const bool listenPort9898,
+ const bool outputMessage, const bool includeVoltage, XiaomiGateway *parent)
+- : socket_(io_service, boost::asio::ip::udp::v4())
++ : socket_(io_context, boost::asio::ip::udp::v4())
+ {
+ m_HardwareID = m_HwdID;
+ m_XiaomiGateway = parent;
+@@ -1196,8 +1195,8 @@ XiaomiGateway::xiaomi_udp_server::xiaomi_udp_server(boost::asio::io_service &io_
+ if (!m_localip.empty())
+ {
+ boost::system::error_code ec;
+- boost::asio::ip::address listen_addr = boost::asio::ip::address::from_string(m_localip, ec);
+- boost::asio::ip::address mcast_addr = boost::asio::ip::address::from_string("224.0.0.50", ec);
++ boost::asio::ip::address listen_addr = boost::asio::ip::make_address_v4(m_localip, ec);
++ boost::asio::ip::address mcast_addr = boost::asio::ip::make_address_v4("224.0.0.50", ec);
+ boost::asio::ip::udp::endpoint listen_endpoint(mcast_addr, 9898);
+
+ socket_.bind(boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 9898));
+@@ -1213,9 +1212,9 @@ XiaomiGateway::xiaomi_udp_server::xiaomi_udp_server(boost::asio::io_service &io_
+ socket_.bind(boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 9898));
+ std::shared_ptr<std::string> message(new std::string(R"({"cmd":"whois"})"));
+ boost::asio::ip::udp::endpoint remote_endpoint;
+- remote_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::address::from_string("224.0.0.50"), 4321);
++ remote_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::make_address_v4("224.0.0.50"), 4321);
+ socket_.send_to(boost::asio::buffer(*message), remote_endpoint);
+- socket_.set_option(boost::asio::ip::multicast::join_group(boost::asio::ip::address::from_string("224.0.0.50")));
++ socket_.set_option(boost::asio::ip::multicast::join_group(boost::asio::ip::make_address_v4("224.0.0.50")));
+ }
+ }
+ catch (const boost::system::system_error &ex)
+@@ -1720,7 +1719,7 @@ void XiaomiGateway::xiaomi_udp_server::handle_receive(const boost::system::error
+ message.append("\"}");
+ std::shared_ptr<std::string> message1(new std::string(message));
+ boost::asio::ip::udp::endpoint remote_endpoint;
+- remote_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::address::from_string(TrueGateway->GetGatewayIp().c_str()), 9898);
++ remote_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::make_address_v4(TrueGateway->GetGatewayIp().c_str()), 9898);
+ socket_.send_to(boost::asio::buffer(*message1), remote_endpoint);
+ }
+ }
+@@ -1746,7 +1745,7 @@ void XiaomiGateway::xiaomi_udp_server::handle_receive(const boost::system::error
+ std::string message = R"({"cmd" : "get_id_list"})";
+ std::shared_ptr<std::string> message2(new std::string(message));
+ boost::asio::ip::udp::endpoint remote_endpoint;
+- remote_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::address::from_string(TrueGateway->GetGatewayIp().c_str()), 9898);
++ remote_endpoint = boost::asio::ip::udp::endpoint(boost::asio::ip::make_address_v4(TrueGateway->GetGatewayIp().c_str()), 9898);
+ socket_.send_to(boost::asio::buffer(*message2), remote_endpoint);
+ }
+ }
+diff --git hardware/XiaomiGateway.h hardware/XiaomiGateway.h
+index dce4b34..1f552f3 100644
+--- hardware/XiaomiGateway.h
++++ hardware/XiaomiGateway.h
+@@ -100,7 +100,7 @@ class XiaomiGateway : public CDomoticzHardwareBase
+ class xiaomi_udp_server
+ {
+ public:
+- xiaomi_udp_server(boost::asio::io_service &io_service, int m_HwdID, const std::string &gatewayIp, const std::string &localIp, bool listenPort9898, bool outputMessage,
++ xiaomi_udp_server(boost::asio::io_context &io_context, int m_HwdID, const std::string &gatewayIp, const std::string &localIp, bool listenPort9898, bool outputMessage,
+ bool includeVolage, XiaomiGateway *parent);
+ ~xiaomi_udp_server() = default;
+
+diff --git hardware/Yeelight.cpp hardware/Yeelight.cpp
+index cdb7889..e5fe8fc 100644
+--- hardware/Yeelight.cpp
++++ hardware/Yeelight.cpp
+@@ -93,8 +93,8 @@ void Yeelight::Do_Work()
+
+ try
+ {
+- boost::asio::io_service io_service;
+- udp_server server(io_service, m_HwdID);
++ boost::asio::io_context io_context;
++ udp_server server(io_context, m_HwdID);
+ int sec_counter = YEELIGHT_POLL_INTERVAL - 5;
+ while (!IsStopRequested(1000))
+ {
+@@ -105,7 +105,7 @@ void Yeelight::Do_Work()
+ if (sec_counter % 60 == 0) //poll YeeLights every minute
+ {
+ server.start_send();
+- io_service.run();
++ io_context.run();
+ }
+ }
+ }
+@@ -227,12 +227,11 @@ bool Yeelight::WriteToHardware(const char *pdata, const unsigned char length)
+
+ try
+ {
+- boost::asio::io_service io_service;
+- boost::asio::ip::tcp::socket sendSocket(io_service);
+- boost::asio::ip::tcp::resolver resolver(io_service);
+- boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), szTmp, "55443");
+- auto iterator = resolver.resolve(query);
+- boost::asio::connect(sendSocket, iterator);
++ boost::asio::io_context io_context;
++ boost::asio::ip::tcp::socket sendSocket(io_context);
++ boost::asio::ip::tcp::resolver resolver(io_context);
++ auto endpoints = resolver.resolve(boost::asio::ip::tcp::v4(), szTmp, "55443");
++ boost::asio::connect(sendSocket, endpoints);
+
+ std::string message;
+ std::string message2;
+@@ -404,8 +403,8 @@ bool Yeelight::WriteToHardware(const char *pdata, const unsigned char length)
+ std::array<char, 1024> recv_buffer_;
+ int hardwareId;
+
+-Yeelight::udp_server::udp_server(boost::asio::io_service& io_service, int m_HwdID)
+- : socket_(io_service, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0))
++Yeelight::udp_server::udp_server(boost::asio::io_context& io_context, int m_HwdID)
++ : socket_(io_context, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0))
+ {
+ socket_.set_option(boost::asio::ip::udp::socket::reuse_address(true));
+ socket_.set_option(boost::asio::socket_base::broadcast(true));
+@@ -421,7 +420,7 @@ void Yeelight::udp_server::start_send()
+ //Log(LOG_STATUS, "start_send..................");
+ std::shared_ptr<std::string> message(
+ new std::string(testMessage));
+- remote_endpoint_ = boost::asio::ip::udp::endpoint(boost::asio::ip::address::from_string("239.255.255.250"), 1982);
++ remote_endpoint_ = boost::asio::ip::udp::endpoint(boost::asio::ip::make_address_v4("239.255.255.250"), 1982);
+ socket_.send_to(boost::asio::buffer(*message), remote_endpoint_);
+ sleep_milliseconds(150);
+ start_receive();
+diff --git hardware/Yeelight.h hardware/Yeelight.h
+index fb03c28..3b7b4c3 100644
+--- hardware/Yeelight.h
++++ hardware/Yeelight.h
+@@ -25,7 +25,7 @@ class Yeelight : public CDomoticzHardwareBase
+ class udp_server
+ {
+ public:
+- udp_server(boost::asio::io_service &io_service, int m_HwdID);
++ udp_server(boost::asio::io_context &io_context, int m_HwdID);
+ boost::asio::ip::udp::socket socket_;
+ boost::asio::ip::udp::endpoint remote_endpoint_;
+ void start_send();
+diff --git hardware/plugins/PluginManager.cpp hardware/plugins/PluginManager.cpp
+index 2813112..423edbb 100644
+--- hardware/plugins/PluginManager.cpp
++++ hardware/plugins/PluginManager.cpp
+@@ -64,7 +64,7 @@ namespace Plugins {
+ // PyMODINIT_FUNC PyInit_DomoticzEvents(void);
+
+ std::mutex PluginMutex; // controls accessto the message queue and m_pPlugins map
+- boost::asio::io_service ios;
++ boost::asio::io_context ios;
+
+ std::map<int, CDomoticzHardwareBase*> CPluginSystem::m_pPlugins;
+ std::map<std::string, std::string> CPluginSystem::m_PluginXml;
+@@ -315,7 +315,7 @@ namespace Plugins {
+ // Create initial IO Service thread
+ ios.restart();
+ // Create some work to keep IO Service alive
+- auto work = boost::asio::io_service::work(ios);
++ auto work = boost::asio::make_work_guard(ios);
+ boost::thread_group BoostThreads;
+ for (int i = 0; i < 1; i++)
+ {
+diff --git hardware/plugins/PluginTransports.cpp hardware/plugins/PluginTransports.cpp
+index 52d14e7..f7ace0f 100644
+--- hardware/plugins/PluginTransports.cpp
++++ hardware/plugins/PluginTransports.cpp
+@@ -116,15 +116,14 @@ namespace Plugins {
+ m_bConnected = false;
+ m_Socket = new boost::asio::ip::tcp::socket(ios);
+
+- boost::system::error_code ec;
+- boost::asio::ip::tcp::resolver::query query(m_IP, m_Port);
+- auto iter = m_Resolver.resolve(query);
+- boost::asio::ip::tcp::endpoint endpoint = *iter;
+-
+ //
+ // Async resolve/connect based on http://www.boost.org/doc/libs/1_45_0/doc/html/boost_asio/example/http/client/async_client.cpp
+ //
+- m_Resolver.async_resolve(query, [this](auto &&err, auto end) { handleAsyncResolve(err, end); });
++ m_Resolver.async_resolve(m_IP, m_Port,
++ [this](auto &&err, auto endpoints) {
++ handleAsyncResolve(err, endpoints);
++ }
++ );
+ }
+ }
+ catch (std::exception& e)
+@@ -139,15 +138,14 @@ namespace Plugins {
+ return true;
+ }
+
+- void CPluginTransportTCP::handleAsyncResolve(const boost::system::error_code & err, boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
++ void CPluginTransportTCP::handleAsyncResolve(const boost::system::error_code & err, boost::asio::ip::tcp::resolver::results_type endpoints)
+ {
+ CPlugin* pPlugin = ((CConnection*)m_pConnection)->pPlugin;
+ AccessPython Guard(pPlugin, "CPluginTransportTCP::handleAsyncResolve");
+
+ if (!err)
+ {
+- boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator;
+- m_Socket->async_connect(endpoint, [this, endpoint_iterator](auto &&err) mutable { handleAsyncConnect(err, ++endpoint_iterator); });
++ boost::asio::async_connect(*m_Socket, endpoints, [this](auto &&err, const boost::asio::ip::tcp::endpoint &endpoint) mutable { handleAsyncConnect(err, endpoint); });
+ }
+ else
+ {
+@@ -169,7 +167,7 @@ namespace Plugins {
+ }
+ }
+
+- void CPluginTransportTCP::handleAsyncConnect(const boost::system::error_code &err, const boost::asio::ip::tcp::resolver::iterator &endpoint_iterator)
++ void CPluginTransportTCP::handleAsyncConnect(const boost::system::error_code &err, const boost::asio::ip::tcp::endpoint &endpoint)
+ {
+ CPlugin* pPlugin = ((CConnection*)m_pConnection)->pPlugin;
+ AccessPython Guard(pPlugin, "CPluginTransportTCP::handleAsyncResolve");
+@@ -481,7 +479,7 @@ namespace Plugins {
+ }
+ };
+
+- void CPluginTransportTCPSecure::handleAsyncConnect(const boost::system::error_code &err, const boost::asio::ip::tcp::resolver::iterator &endpoint_iterator)
++ void CPluginTransportTCPSecure::handleAsyncConnect(const boost::system::error_code &err, const boost::asio::ip::tcp::endpoint &endpoint)
+ {
+ CPlugin* pPlugin = ((CConnection*)m_pConnection)->pPlugin;
+ if (!pPlugin) return;
+@@ -498,7 +496,7 @@ namespace Plugins {
+ SSL_set_tlsext_host_name(m_TLSSock->native_handle(), m_IP.c_str()); // Enable SNI
+
+ m_TLSSock->set_verify_mode(boost::asio::ssl::verify_none);
+- m_TLSSock->set_verify_callback(boost::asio::ssl::rfc2818_verification(m_IP));
++ m_TLSSock->set_verify_callback(boost::asio::ssl::host_name_verification(m_IP));
+ // m_TLSSock->set_verify_callback([this](auto v, auto &c){ VerifyCertificate(v, c);});
+ try
+ {
+@@ -648,7 +646,7 @@ namespace Plugins {
+ // Hanlde multicast
+ if (((m_IP.substr(0, 4) >= "224.") && (m_IP.substr(0, 4) <= "239.")) || (m_IP.substr(0, 4) == "255."))
+ {
+- m_Socket->set_option(boost::asio::ip::multicast::join_group(boost::asio::ip::address::from_string(m_IP.c_str())), ec);
++ m_Socket->set_option(boost::asio::ip::multicast::join_group(boost::asio::ip::make_address_v4(m_IP.c_str())), ec);
+ m_Socket->set_option(boost::asio::ip::multicast::hops(2), ec);
+ }
+ }
+@@ -764,7 +762,7 @@ namespace Plugins {
+ }
+ else
+ {
+- boost::asio::ip::udp::endpoint destination(boost::asio::ip::address::from_string(m_IP.c_str()), atoi(m_Port.c_str()));
++ boost::asio::ip::udp::endpoint destination(boost::asio::ip::make_address_v4(m_IP.c_str()), atoi(m_Port.c_str()));
+ size_t bytes_transferred = m_Socket->send_to(boost::asio::buffer(pMessage, pMessage.size()), destination);
+ }
+ }
+@@ -825,12 +823,14 @@ namespace Plugins {
+ }
+ };
+
+- void CPluginTransportICMP::handleAsyncResolve(const boost::system::error_code &ec, const boost::asio::ip::icmp::resolver::iterator &endpoint_iterator)
++ void CPluginTransportICMP::handleAsyncResolve(const boost::system::error_code &ec, boost::asio::ip::icmp::resolver::results_type endpoints)
+ {
+ if (!ec)
+ {
++ m_Endpoint = endpoints.begin()->endpoint();
++ m_IP = m_Endpoint.address().to_string();
++
+ m_bConnected = true;
+- m_IP = endpoint_iterator->endpoint().address().to_string();
+
+ // Listen will fail (10022 - bad parameter) unless something has been sent(?)
+ std::string body("ping");
+@@ -857,15 +857,11 @@ namespace Plugins {
+ m_bConnecting = true;
+ m_Socket = new boost::asio::ip::icmp::socket(ios, boost::asio::ip::icmp::v4());
+
+- boost::system::error_code ec;
+- boost::asio::ip::icmp::resolver::query query(boost::asio::ip::icmp::v4(), m_IP, "");
+- auto iter = m_Resolver.resolve(query);
+- m_Endpoint = *iter;
+-
+- //
+- // Async resolve/connect based on http://www.boost.org/doc/libs/1_51_0/doc/html/boost_asio/example/icmp/ping.cpp
+- //
+- m_Resolver.async_resolve(query, [this](auto &&err, auto i) { handleAsyncResolve(err, i); });
++ m_Resolver.async_resolve(boost::asio::ip::icmp::v4(), m_IP, "",
++ [this](auto &&err, auto endpoints) {
++ handleAsyncResolve(err, endpoints);
++ }
++ );
+ }
+ else
+ {
+diff --git hardware/plugins/PluginTransports.h hardware/plugins/PluginTransports.h
+index c1cc1e3..79d5725 100644
+--- hardware/plugins/PluginTransports.h
++++ hardware/plugins/PluginTransports.h
+@@ -6,7 +6,7 @@
+
+ namespace Plugins {
+
+- extern boost::asio::io_service ios;
++ extern boost::asio::io_context ios;
+
+ class CPluginTransport
+ {
+@@ -85,8 +85,8 @@ namespace Plugins {
+ , m_Socket(nullptr){};
+ bool handleConnect() override;
+ bool handleListen() override;
+- virtual void handleAsyncResolve(const boost::system::error_code &err, boost::asio::ip::tcp::resolver::iterator endpoint_iterator);
+- virtual void handleAsyncConnect(const boost::system::error_code &err, const boost::asio::ip::tcp::resolver::iterator &endpoint_iterator);
++ virtual void handleAsyncResolve(const boost::system::error_code &err, boost::asio::ip::tcp::resolver::results_type endpoints);
++ virtual void handleAsyncConnect(const boost::system::error_code &err, const boost::asio::ip::tcp::endpoint &endpoint);
+ virtual void handleAsyncAccept(boost::asio::ip::tcp::socket *pSocket, const boost::system::error_code &error);
+ void handleRead(const boost::system::error_code &e, std::size_t bytes_transferred) override;
+ void handleWrite(const std::vector<byte> &pMessage) override;
+@@ -111,7 +111,7 @@ namespace Plugins {
+ : CPluginTransportTCP(HwdID, pConnection, Address, Port)
+ , m_Context(nullptr)
+ , m_TLSSock(nullptr){};
+- void handleAsyncConnect(const boost::system::error_code &err, const boost::asio::ip::tcp::resolver::iterator &endpoint_iterator) override;
++ void handleAsyncConnect(const boost::system::error_code &err, const boost::asio::ip::tcp::endpoint &endpoint) override;
+ void handleRead(const boost::system::error_code &e, std::size_t bytes_transferred) override;
+ void handleWrite(const std::vector<byte> &pMessage) override;
+ ~CPluginTransportTCPSecure() override;
+@@ -151,7 +151,7 @@ namespace Plugins {
+ , m_Socket(nullptr)
+ , m_Timer(nullptr)
+ , m_SequenceNo(-1){};
+- void handleAsyncResolve(const boost::system::error_code &err, const boost::asio::ip::icmp::resolver::iterator &endpoint_iterator);
++ void handleAsyncResolve(const boost::system::error_code &err, boost::asio::ip::icmp::resolver::results_type endpoints);
+ bool handleListen() override;
+ void handleTimeout(const boost::system::error_code &) override;
+ void handleRead(const boost::system::error_code &e, std::size_t bytes_transferred) override;
+diff --git main/WebServerCmds.cpp main/WebServerCmds.cpp
+index 7d4a9f2..3586373 100644
+--- main/WebServerCmds.cpp
++++ main/WebServerCmds.cpp
+@@ -1632,7 +1632,7 @@ namespace http
+ ExtraHeaders.push_back("App_Revision: " + std::to_string(iAppRevision));
+ ExtraHeaders.push_back("System_Name: " + systemname);
+ ExtraHeaders.push_back("Machine: " + machine);
+- ExtraHeaders.push_back("Type: " + (!bIsBetaChannel) ? "Stable" : "Beta");
++ ExtraHeaders.push_back("Type: " + std::string(!bIsBetaChannel ? "Stable" : "Beta"));
+
+ if (!HTTPClient::GET(szHistoryURL, ExtraHeaders, historyfile))
+ {
+diff --git main/mainworker.cpp main/mainworker.cpp
+index b5027eb..b8f8dc7 100644
+--- main/mainworker.cpp
++++ main/mainworker.cpp
+@@ -1318,7 +1318,7 @@ bool MainWorker::IsUpdateAvailable(const bool bIsForced)
+ ExtraHeaders.push_back("App_Revision: " + std::to_string(iAppRevision));
+ ExtraHeaders.push_back("System_Name: " + m_szSystemName);
+ ExtraHeaders.push_back("Machine: " + machine);
+- ExtraHeaders.push_back("Type: " + (!bIsBetaChannel) ? "Stable" : "Beta");
++ ExtraHeaders.push_back("Type: " + std::string(!bIsBetaChannel ? "Stable" : "Beta"));
+
+ if (!HTTPClient::GET(szURL, ExtraHeaders, revfile))
+ return false;
+diff --git plugins/examples/Pinger.py plugins/examples/Pinger.py
+index 6b54559..c7a776d 100644
+--- plugins/examples/Pinger.py
++++ plugins/examples/Pinger.py
+@@ -3,7 +3,7 @@
+ # Author: Dnpwwo, 2017 - 2018
+ #
+ """
+-<plugin key="ICMP" name="Pinger (ICMP)" author="dnpwwo" version="3.1.4">
++<plugin key="ICMP" name="Pinger (ICMP)" author="dnpwwo" version="3.1.5">
+ <description>
+ ICMP Pinger Plugin.<br/><br/>
+ Specify comma delimted addresses (IP or DNS names) of devices that are to be pinged.<br/>
+@@ -144,8 +144,9 @@ class BasePlugin:
+ for Device in Devices:
+ if (("Name" in Devices[Device].Options) and (Devices[Device].Options["Name"] == Connection.Name)):
+ UpdateDevice(Device, 0, "Off", TimedOut)
+- self.icmpConn.Close()
+- self.icmpConn = None
++ if (self.icmpConn != None):
++ self.icmpConn.Close()
++ self.icmpConn = None
+
+ def onHeartbeat(self):
+ Domoticz.Debug("Heartbeating...")
+diff --git push/MQTTPush.h push/MQTTPush.h
+index 0773b43..d9f9332 100644
+--- push/MQTTPush.h
++++ push/MQTTPush.h
+@@ -14,7 +14,7 @@ public:
+ void on_message(const struct mosquitto_message* message) override;
+ void on_connect(int rc) override;
+ void on_disconnect(int rc) override;
+- void on_going_down();
++ void on_going_down() override;
+ private:
+ struct _tPushItem
+ {
+diff --git tcpserver/TCPClient.cpp tcpserver/TCPClient.cpp
+index d55da10..3eee093 100644
+--- tcpserver/TCPClient.cpp
++++ tcpserver/TCPClient.cpp
+@@ -19,7 +19,7 @@ namespace tcp {
+ delete socket_;
+ }
+
+- CTCPClient::CTCPClient(boost::asio::io_service& ios, CTCPServerIntBase* pManager)
++ CTCPClient::CTCPClient(boost::asio::io_context& ios, CTCPServerIntBase* pManager)
+ : CTCPClientBase(pManager)
+ {
+ socket_ = new boost::asio::ip::tcp::socket(ios);
+diff --git tcpserver/TCPClient.h tcpserver/TCPClient.h
+index df4350d..e7a882b 100644
+--- tcpserver/TCPClient.h
++++ tcpserver/TCPClient.h
+@@ -38,7 +38,7 @@ class CTCPClient : public CTCPClientBase,
+ public std::enable_shared_from_this<CTCPClient>
+ {
+ public:
+- CTCPClient(boost::asio::io_service& ios, CTCPServerIntBase *pManager);
++ CTCPClient(boost::asio::io_context& ios, CTCPServerIntBase *pManager);
+ ~CTCPClient() = default;
+ void start() override;
+ void stop() override;
+diff --git tcpserver/TCPServer.cpp tcpserver/TCPServer.cpp
+index 91fdc7e..57f8709 100644
+--- tcpserver/TCPServer.cpp
++++ tcpserver/TCPServer.cpp
+@@ -18,14 +18,14 @@ namespace tcp {
+
+ CTCPServerInt::CTCPServerInt(const std::string& address, const std::string& port, CTCPServer* pRoot) :
+ CTCPServerIntBase(pRoot),
+- io_service_(),
+- acceptor_(io_service_)
++ io_context_(),
++ acceptor_(io_context_)
+ {
+ // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
+- boost::asio::ip::tcp::resolver resolver(io_service_);
+- boost::asio::ip::tcp::resolver::query query(address, port);
+- boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
+- acceptor_.open(endpoint.protocol());
++ boost::asio::ip::tcp::resolver resolver(io_context_);
++ boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::results_type endpoints = resolver.resolve(address, port);
++ auto endpoint = *endpoints.begin();
++ acceptor_.open(endpoint.endpoint().protocol());
+ acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+ // bind to both ipv6 and ipv4 sockets for the "::" address only
+ if (address == "::")
+@@ -35,7 +35,7 @@ namespace tcp {
+ acceptor_.bind(endpoint);
+ acceptor_.listen();
+
+- new_connection_ = std::make_shared<CTCPClient>(io_service_, this);
++ new_connection_ = std::make_shared<CTCPClient>(io_context_, this);
+ if (new_connection_ == nullptr)
+ {
+ _log.Log(LOG_ERROR, "Error creating new client!");
+@@ -47,24 +47,24 @@ namespace tcp {
+
+ void CTCPServerInt::start()
+ {
+- // The io_service::run() call will block until all asynchronous operations
++ // The io_context::run() call will block until all asynchronous operations
+ // have finished. While the server is running, there is always at least one
+ // asynchronous operation outstanding: the asynchronous accept call waiting
+ // for new incoming connections.
+- io_service_.run();
++ io_context_.run();
+ }
+
+ void CTCPServerInt::stop()
+ {
+ // Post a call to the stop function so that server::stop() is safe to call
+ // from any thread.
+- io_service_.post([this] { handle_stop(); });
++ boost::asio::post([this] { handle_stop(); });
+ }
+
+ void CTCPServerInt::handle_stop()
+ {
+ // The server is stopped by cancelling all outstanding asynchronous
+- // operations. Once all operations have finished the io_service::run() call
++ // operations. Once all operations have finished the io_context::run() call
+ // will exit.
+ acceptor_.close();
+ stopAllClients();
+@@ -88,7 +88,7 @@ namespace tcp {
+ connections_.insert(new_connection_);
+ new_connection_->start();
+
+- new_connection_.reset(new CTCPClient(io_service_, this));
++ new_connection_.reset(new CTCPClient(io_context_, this));
+
+ acceptor_.async_accept(*(new_connection_->socket()), [this](auto&& err) { handleAccept(err); });
+ }
+diff --git tcpserver/TCPServer.h tcpserver/TCPServer.h
+index ca611b1..17284ca 100644
+--- tcpserver/TCPServer.h
++++ tcpserver/TCPServer.h
+@@ -70,8 +70,8 @@ private:
+ /// Handle a request to stop the server.
+ void handle_stop();
+
+- /// The io_service used to perform asynchronous operations.
+- boost::asio::io_service io_service_;
++ /// The io_context used to perform asynchronous operations.
++ boost::asio::io_context io_context_;
+
+ boost::asio::ip::tcp::acceptor acceptor_;
+
+diff --git webserver/cWebem.cpp webserver/cWebem.cpp
+index 57d9683..c0d292d 100644
+--- webserver/cWebem.cpp
++++ webserver/cWebem.cpp
+@@ -47,13 +47,13 @@ namespace http {
+ , myRequestHandler(doc_root, this)
+ // Rene, make sure we initialize m_sessions first, before starting a server
+ , myServer(server_factory::create(settings, myRequestHandler))
+- , m_io_service()
+- , m_session_clean_timer(m_io_service, boost::posix_time::minutes(1))
++ , m_io_context()
++ , m_session_clean_timer(m_io_context, boost::posix_time::minutes(1))
+ {
+ // associate handler to timer and schedule the first iteration
+ m_session_clean_timer.async_wait([this](auto &&) { CleanSessions(); });
+- m_io_service_thread = std::make_shared<std::thread>([p = &m_io_service] { p->run(); });
+- SetThreadName(m_io_service_thread->native_handle(), "Webem_ssncleaner");
++ m_io_context_thread = std::make_shared<std::thread>([p = &m_io_context] { p->run(); });
++ SetThreadName(m_io_context_thread->native_handle(), "Webem_ssncleaner");
+ }
+
+ cWebem::~cWebem()
+@@ -93,14 +93,14 @@ namespace http {
+ // Stop session cleaner
+ try
+ {
+- if (!m_io_service.stopped())
++ if (!m_io_context.stopped())
+ {
+- m_io_service.stop();
++ m_io_context.stop();
+ }
+- if (m_io_service_thread)
++ if (m_io_context_thread)
+ {
+- m_io_service_thread->join();
+- m_io_service_thread.reset();
++ m_io_context_thread->join();
++ m_io_context_thread.reset();
+ }
+ }
+ catch (...)
+diff --git webserver/cWebem.h webserver/cWebem.h
+index 6e3b899..7905c45 100644
+--- webserver/cWebem.h
++++ webserver/cWebem.h
+@@ -259,9 +259,9 @@ namespace http
+ std::string m_webRoot;
+ /// sessions management
+ std::mutex m_sessionsMutex;
+- boost::asio::io_service m_io_service;
++ boost::asio::io_context m_io_context;
+ boost::asio::deadline_timer m_session_clean_timer;
+- std::shared_ptr<std::thread> m_io_service_thread;
++ std::shared_ptr<std::thread> m_io_context_thread;
+ };
+
+ } // namespace server
+diff --git webserver/connection.cpp webserver/connection.cpp
+index 40f9788..3a70924 100644
+--- webserver/connection.cpp
++++ webserver/connection.cpp
+@@ -22,13 +22,13 @@ namespace http {
+ extern time_t last_write_time(const std::string& path);
+
+ // this is the constructor for plain connections
+- connection::connection(boost::asio::io_service &io_service, connection_manager &manager, request_handler &handler, int read_timeout)
++ connection::connection(boost::asio::io_context &io_context, connection_manager &manager, request_handler &handler, int read_timeout)
+ : send_buffer_(nullptr)
+ , read_timeout_(read_timeout)
+- , read_timer_(io_service, boost::posix_time::seconds(read_timeout))
++ , read_timer_(io_context, boost::posix_time::seconds(read_timeout))
+ , default_abandoned_timeout_(20 * 60)
+ // 20mn before stopping abandoned connection
+- , abandoned_timer_(io_service, boost::posix_time::seconds(default_abandoned_timeout_))
++ , abandoned_timer_(io_context, boost::posix_time::seconds(default_abandoned_timeout_))
+ , connection_manager_(manager)
+ , request_handler_(handler)
+ , status_(INITIALIZING)
+@@ -39,18 +39,18 @@ namespace http {
+ keepalive_ = false;
+ write_in_progress = false;
+ connection_type = ConnectionType::connection_http;
+- socket_ = std::make_unique<boost::asio::ip::tcp::socket>(io_service);
++ socket_ = std::make_unique<boost::asio::ip::tcp::socket>(io_context);
+ }
+
+ #ifdef WWW_ENABLE_SSL
+ // this is the constructor for secure connections
+- connection::connection(boost::asio::io_service &io_service, connection_manager &manager, request_handler &handler, int read_timeout, boost::asio::ssl::context &context)
++ connection::connection(boost::asio::io_context &io_context, connection_manager &manager, request_handler &handler, int read_timeout, boost::asio::ssl::context &context)
+ : send_buffer_(nullptr)
+ , read_timeout_(read_timeout)
+- , read_timer_(io_service, boost::posix_time::seconds(read_timeout))
++ , read_timer_(io_context, boost::posix_time::seconds(read_timeout))
+ , default_abandoned_timeout_(20 * 60)
+ // 20mn before stopping abandoned connection
+- , abandoned_timer_(io_service, boost::posix_time::seconds(default_abandoned_timeout_))
++ , abandoned_timer_(io_context, boost::posix_time::seconds(default_abandoned_timeout_))
+ , connection_manager_(manager)
+ , request_handler_(handler)
+ , status_(INITIALIZING)
+@@ -62,7 +62,7 @@ namespace http {
+ write_in_progress = false;
+ connection_type = ConnectionType::connection_http;
+ socket_ = nullptr;
+- sslsocket_ = std::make_unique<ssl_socket>(io_service, context);
++ sslsocket_ = std::make_unique<ssl_socket>(io_context, context);
+ }
+ #endif
+
+@@ -152,9 +152,9 @@ namespace http {
+ if (error != boost::asio::error::operation_aborted) {
+ switch (connection_type) {
+ case ConnectionType::connection_http:
+- // Timers should be cancelled before stopping to remove tasks from the io_service.
+- // The io_service will stop naturally when every tasks are removed.
+- // If timers are not cancelled, the exception ERROR_ABANDONED_WAIT_0 is thrown up to the io_service::run() caller.
++ // Timers should be cancelled before stopping to remove tasks from the io_context.
++ // The io_context will stop naturally when every tasks are removed.
++ // If timers are not cancelled, the exception ERROR_ABANDONED_WAIT_0 is thrown up to the io_context::run() caller.
+ cancel_abandoned_timeout();
+ cancel_read_timeout();
+
+@@ -372,7 +372,7 @@ namespace http {
+ switch (connection_type)
+ {
+ case ConnectionType::connection_http:
+- begin = boost::asio::buffer_cast<const char*>(_buf.data());
++ begin = static_cast<const char*>(_buf.data().data());
+ try
+ {
+ request_parser_.reset();
+@@ -404,7 +404,7 @@ namespace http {
+ newt = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
+ }
+
+- size_t sizeread = begin - boost::asio::buffer_cast<const char*>(_buf.data());
++ size_t sizeread = begin - static_cast<const char*>(_buf.data().data());
+ _buf.consume(sizeread);
+ reply_.reset();
+ const char* pConnection = request_.get_req_header(&request_, "Connection");
+@@ -520,7 +520,7 @@ namespace http {
+ break;
+ case ConnectionType::connection_websocket:
+ case ConnectionType::connection_websocket_closing:
+- begin = boost::asio::buffer_cast<const char*>(_buf.data());
++ begin = static_cast<const char*>(_buf.data().data());
+ result = websocket_parser.parse((const unsigned char*)begin, _buf.size(), bytes_consumed, keepalive_);
+ _buf.consume(bytes_consumed);
+ if (result) {
+diff --git webserver/connection.hpp webserver/connection.hpp
+index ce452b5..c1a82c5 100644
+--- webserver/connection.hpp
++++ webserver/connection.hpp
+@@ -43,11 +43,11 @@ namespace http {
+ std::string host_local_endpoint_port_;
+ std::string host_last_request_uri_;
+ };
+- /// Construct a connection with the given io_service.
+- explicit connection(boost::asio::io_service& io_service,
++ /// Construct a connection with the given io_context.
++ explicit connection(boost::asio::io_context& io_context,
+ connection_manager& manager, request_handler& handler, int timeout);
+ #ifdef WWW_ENABLE_SSL
+- explicit connection(boost::asio::io_service& io_service,
++ explicit connection(boost::asio::io_context& io_context,
+ connection_manager& manager, request_handler& handler, int timeout, boost::asio::ssl::context& context);
+ #endif
+ ~connection() = default;
+diff --git webserver/server.cpp webserver/server.cpp
+index da15887..8bdfc13 100644
+--- webserver/server.cpp
++++ webserver/server.cpp
+@@ -13,15 +13,15 @@ namespace http {
+ namespace server {
+
+ server_base::server_base(const server_settings &settings, request_handler &user_request_handler)
+- : io_service_()
+- , acceptor_(io_service_)
++ : io_context_()
++ , acceptor_(io_context_)
+ , request_handler_(user_request_handler)
+ , settings_(settings)
+ , timeout_(20)
+ , // default read timeout in seconds
+ is_running(false)
+ , is_stop_complete(false)
+- , m_heartbeat_timer(io_service_)
++ , m_heartbeat_timer(io_context_)
+ {
+ if (!settings.is_enabled())
+ {
+@@ -39,10 +39,10 @@ namespace server {
+ }
+
+ // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
+- boost::asio::ip::tcp::resolver resolver(io_service_);
+- boost::asio::ip::tcp::resolver::query query(settings_.listening_address, settings_.listening_port);
+- boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
+- acceptor_.open(endpoint.protocol());
++ boost::asio::ip::tcp::resolver resolver(io_context_);
++ boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::results_type endpoints = resolver.resolve(settings_.listening_address, settings_.listening_port);
++ auto endpoint = *endpoints.begin();
++ acceptor_.open(endpoint.endpoint().protocol());
+ acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+ // bind to both ipv6 and ipv4 sockets for the "::" address only
+ if (settings_.listening_address == "::")
+@@ -59,28 +59,28 @@ namespace server {
+ }
+
+ void server_base::run() {
+- // The io_service::run() call will block until all asynchronous operations
++ // The io_context::run() call will block until all asynchronous operations
+ // have finished. While the server is running, there is always at least one
+ // asynchronous operation outstanding: the asynchronous accept call waiting
+ // for new incoming connections.
+ try {
+ is_running = true;
+ heart_beat(boost::system::error_code());
+- io_service_.run();
++ io_context_.run();
+ is_running = false;
+ } catch (std::exception& e) {
+ _log.Log(LOG_ERROR, "[web:%s] exception occurred : '%s' (need to run again)", settings_.listening_port.c_str(), e.what());
+ is_running = false;
+ // Note: if acceptor is up everything is OK, we can call run() again
+ // but if the exception has broken the acceptor we cannot stop/start it and the next run() will exit immediatly.
+- io_service_.reset(); // this call is needed before calling run() again
++ io_context_.restart(); // this call is needed before calling run() again
+ throw;
+ } catch (...) {
+ _log.Log(LOG_ERROR, "[web:%s] unknown exception occurred (need to run again)", settings_.listening_port.c_str());
+ is_running = false;
+ // Note: if acceptor is up everything is OK, we can call run() again
+ // but if the exception has broken the acceptor we cannot stop/start it and the next run() will exit immediatly.
+- io_service_.reset(); // this call is needed before calling run() again
++ io_context_.restart(); // this call is needed before calling run() again
+ throw;
+ }
+ }
+@@ -89,12 +89,12 @@ void server_base::run() {
+ void server_base::stop() {
+ if (is_running) {
+ // Post a call to the stop function so that server_base::stop() is safe to call from any thread.
+- // Rene, set is_running to false, because the following is an io_service call, which makes is_running
++ // Rene, set is_running to false, because the following is an io_context call, which makes is_running
+ // never set to false whilst in the call itself
+ is_running = false;
+- io_service_.post([this] { handle_stop(); });
++ boost::asio::post(io_context_, [this] { handle_stop(); });
+ } else {
+- // if io_service is not running then the post call will not be performed
++ // if io_context is not running then the post call will not be performed
+ handle_stop();
+ }
+
+@@ -112,7 +112,7 @@ void server_base::stop() {
+ }
+ sleep_milliseconds(500);
+ }
+- io_service_.stop();
++ io_context_.stop();
+
+ // Deregister heartbeat
+ m_mainworker.HeartbeatRemove(std::string("WebServer:") + settings_.listening_port);
+@@ -136,7 +136,7 @@ void server_base::heart_beat(const boost::system::error_code& error)
+ m_mainworker.HeartbeatUpdate(std::string("WebServer:") + settings_.listening_port);
+
+ // Schedule next heartbeat
+- m_heartbeat_timer.expires_from_now(std::chrono::seconds(4));
++ m_heartbeat_timer.expires_after(std::chrono::seconds(4));
+ m_heartbeat_timer.async_wait([this](auto &&err) { heart_beat(err); });
+ }
+ }
+@@ -148,7 +148,7 @@ server::server(const server_settings &settings, request_handler &user_request_ha
+ }
+
+ void server::init_connection() {
+- new_connection_.reset(new connection(io_service_, connection_manager_, request_handler_, timeout_));
++ new_connection_.reset(new connection(io_context_, connection_manager_, request_handler_, timeout_));
+ }
+
+ /**
+@@ -157,7 +157,7 @@ void server::init_connection() {
+ void server::handle_accept(const boost::system::error_code& e) {
+ if (!e) {
+ connection_manager_.start(new_connection_);
+- new_connection_.reset(new connection(io_service_,
++ new_connection_.reset(new connection(io_context_,
+ connection_manager_, request_handler_, timeout_));
+ // listen for a subsequent request
+ acceptor_.async_accept(new_connection_->socket(), [this](auto &&err) { handle_accept(err); });
+@@ -267,7 +267,7 @@ void ssl_server::init_connection() {
+ } else {
+ _log.Log(LOG_ERROR, "[web:%s] missing SSL DH parameters file %s!", settings_.listening_port.c_str(), settings_.tmp_dh_file_path.c_str());
+ }
+- new_connection_.reset(new connection(io_service_, connection_manager_, request_handler_, timeout_, context_));
++ new_connection_.reset(new connection(io_context_, connection_manager_, request_handler_, timeout_, context_));
+ }
+
+ void ssl_server::reinit_connection()
+@@ -305,7 +305,7 @@ void ssl_server::reinit_connection()
+ _log.Log(LOG_ERROR, "[web:%s] missing SSL DH parameters from file %s", settings_.listening_port.c_str(), settings_.tmp_dh_file_path.c_str());
+ }
+ }
+- new_connection_.reset(new connection(io_service_, connection_manager_, request_handler_, timeout_, context_));
++ new_connection_.reset(new connection(io_context_, connection_manager_, request_handler_, timeout_, context_));
+ }
+
+ /**
+diff --git webserver/server.hpp webserver/server.hpp
+index f9e71c5..bd7132a 100644
+--- webserver/server.hpp
++++ webserver/server.hpp
+@@ -31,7 +31,7 @@ namespace http
+ explicit server_base(const server_settings &settings, request_handler &user_request_handler);
+ virtual ~server_base() = default;
+
+- /// Run the server's io_service loop.
++ /// Run the server's io_context loop.
+ void run();
+
+ /// Stop the server.
+@@ -46,8 +46,8 @@ namespace http
+ protected:
+ void init(const init_connectionhandler_func &init_connection_handler, accept_handler_func accept_handler);
+
+- /// The io_service used to perform asynchronous operations.
+- boost::asio::io_service io_service_;
++ /// The io_context used to perform asynchronous operations.
++ boost::asio::io_context io_context_;
+
+ /// Acceptor used to listen for incoming connections.
+ boost::asio::ip::tcp::acceptor acceptor_;
diff --git a/www/galene/Makefile b/www/galene/Makefile
index 15cdbfaf3a58..8bea5d198bab 100644
--- a/www/galene/Makefile
+++ b/www/galene/Makefile
@@ -1,6 +1,5 @@
PORTNAME= galene
-DISTVERSION= 0.96
-PORTREVISION= 2
+DISTVERSION= 0.96.3
CATEGORIES= www net-im
MAINTAINER= bapt@FreeBSD.org
@@ -23,32 +22,33 @@ GH_TUPLE= \
davecgh:go-spew:v1.1.1:davecgh_go_spew/vendor/github.com/davecgh/go-spew \
go-yaml:yaml:v3.0.1:go_yaml_yaml/vendor/gopkg.in/yaml.v3 \
golang-jwt:jwt:v5.2.1:golang_jwt_jwt_v5/vendor/github.com/golang-jwt/jwt/v5 \
- golang:crypto:v0.29.0:golang_crypto/vendor/golang.org/x/crypto \
- golang:net:v0.30.0:golang_net/vendor/golang.org/x/net \
- golang:sys:v0.27.0:golang_sys/vendor/golang.org/x/sys \
- golang:term:v0.26.0:golang_term/vendor/golang.org/x/term \
+ golang:crypto:v0.31.0:golang_crypto/vendor/golang.org/x/crypto \
+ golang:net:v0.33.0:golang_net/vendor/golang.org/x/net \
+ golang:sys:v0.28.0:golang_sys/vendor/golang.org/x/sys \
+ golang:term:v0.27.0:golang_term/vendor/golang.org/x/term \
google:uuid:v1.6.0:google_uuid/vendor/github.com/google/uuid \
gorilla:websocket:v1.5.0:gorilla_websocket/vendor/github.com/gorilla/websocket \
jech:cert:f491cf43a77d:jech_cert/vendor/github.com/jech/cert \
jech:samplebuilder:6cbba09fc1c9:jech_samplebuilder/vendor/github.com/jech/samplebuilder \
- pion:datachannel:v1.5.9:pion_datachannel/vendor/github.com/pion/datachannel \
+ pion:datachannel:v1.5.10:pion_datachannel/vendor/github.com/pion/datachannel \
pion:dtls:v2.2.12:pion_dtls_v2/vendor/github.com/pion/dtls/v2 \
pion:ice:v2.3.37:pion_ice_v2/vendor/github.com/pion/ice/v2 \
pion:interceptor:v0.1.37:pion_interceptor/vendor/github.com/pion/interceptor \
pion:logging:v0.2.2:pion_logging/vendor/github.com/pion/logging \
pion:mdns:v0.0.12:pion_mdns/vendor/github.com/pion/mdns \
pion:randutil:v0.1.0:pion_randutil/vendor/github.com/pion/randutil \
- pion:rtcp:v1.2.14:pion_rtcp/vendor/github.com/pion/rtcp \
- pion:rtp:v1.8.9:pion_rtp/vendor/github.com/pion/rtp \
- pion:sctp:v1.8.33:pion_sctp/vendor/github.com/pion/sctp \
+ pion:rtcp:v1.2.15:pion_rtcp/vendor/github.com/pion/rtcp \
+ pion:rtp:v1.8.10:pion_rtp/vendor/github.com/pion/rtp \
+ pion:sctp:v1.8.35:pion_sctp/vendor/github.com/pion/sctp \
pion:sdp:v3.0.9:pion_sdp_v3/vendor/github.com/pion/sdp/v3 \
pion:srtp:v2.0.20:pion_srtp_v2/vendor/github.com/pion/srtp/v2 \
pion:stun:v0.6.1:pion_stun/vendor/github.com/pion/stun \
pion:transport:v2.2.10:pion_transport_v2/vendor/github.com/pion/transport/v2 \
+ pion:transport:v3.0.7:pion_transport_v3/vendor/github.com/pion/transport/v3 \
pion:turn:v2.1.6:pion_turn_v2/vendor/github.com/pion/turn/v2 \
- pion:webrtc:v3.3.4:pion_webrtc_v3/vendor/github.com/pion/webrtc/v3 \
+ pion:webrtc:v3.3.5:pion_webrtc_v3/vendor/github.com/pion/webrtc/v3 \
pmezard:go-difflib:v1.0.0:pmezard_go_difflib/vendor/github.com/pmezard/go-difflib \
- stretchr:testify:v1.9.0:stretchr_testify/vendor/github.com/stretchr/testify \
+ stretchr:testify:v1.10.0:stretchr_testify/vendor/github.com/stretchr/testify \
wlynxg:anet:v0.0.5:wlynxg_anet/vendor/github.com/wlynxg/anet
CGO_ENABLED= 0
diff --git a/www/galene/distinfo b/www/galene/distinfo
index 9bb0479c504f..0191b7d04ad1 100644
--- a/www/galene/distinfo
+++ b/www/galene/distinfo
@@ -1,6 +1,6 @@
-TIMESTAMP = 1735802329
-SHA256 (jech-galene-0.96-galene-0.96_GH0.tar.gz) = fc689fccc718943909cd7585a94574c4a7f7b4168c41028d0d22c73cf6b2dcd6
-SIZE (jech-galene-0.96-galene-0.96_GH0.tar.gz) = 778766
+TIMESTAMP = 1747332374
+SHA256 (jech-galene-0.96.3-galene-0.96.3_GH0.tar.gz) = c76e5b6c059b94d102c2b726ab144ba6a70bdde8135f6733893217172af5201a
+SIZE (jech-galene-0.96.3-galene-0.96.3_GH0.tar.gz) = 888837
SHA256 (at-wat-ebml-go-v0.17.1_GH0.tar.gz) = f058fcf7f4da9f979531a0ba1f811fc34c8d9d30087ba8d442eef220e726cbe3
SIZE (at-wat-ebml-go-v0.17.1_GH0.tar.gz) = 69882
SHA256 (davecgh-go-spew-v1.1.1_GH0.tar.gz) = 7d82b9bb7291adbe7498fe946920ab3e7fc9e6cbfc3b2294693fad00bf0dd17e
@@ -9,14 +9,14 @@ SHA256 (go-yaml-yaml-v3.0.1_GH0.tar.gz) = cf05411540d3e6ef8f1fd88434b34f94cedace
SIZE (go-yaml-yaml-v3.0.1_GH0.tar.gz) = 91173
SHA256 (golang-jwt-jwt-v5.2.1_GH0.tar.gz) = 76d1c81a7cd38ed03309f770f60ac3417f16c75b4c53a0c01bb783863783fef0
SIZE (golang-jwt-jwt-v5.2.1_GH0.tar.gz) = 61340
-SHA256 (golang-crypto-v0.29.0_GH0.tar.gz) = 0f1f747a65c883857c5f6c54b01e228536698dcc5af652386ccfc994c2a3c991
-SIZE (golang-crypto-v0.29.0_GH0.tar.gz) = 1847528
-SHA256 (golang-net-v0.30.0_GH0.tar.gz) = c5bcae30a04fc5c9d6fccfceb368cc1a46413eefdccefdea57336e2b11a1fbfa
-SIZE (golang-net-v0.30.0_GH0.tar.gz) = 1456700
-SHA256 (golang-sys-v0.27.0_GH0.tar.gz) = 91f2021c81184dccca54272abfdfa7f6d0b43fcdf7e36c4d62c1ab597e7988a9
-SIZE (golang-sys-v0.27.0_GH0.tar.gz) = 1518154
-SHA256 (golang-term-v0.26.0_GH0.tar.gz) = 860d9dc2e32939c99ea3590171d8897ca6b876958085fd210d7331787c1ad00b
-SIZE (golang-term-v0.26.0_GH0.tar.gz) = 14688
+SHA256 (golang-crypto-v0.31.0_GH0.tar.gz) = 36e325f89d4cd03ec568d92c74d6affd2b1fb88fcdc63aeb15d1df41e11200ca
+SIZE (golang-crypto-v0.31.0_GH0.tar.gz) = 1837859
+SHA256 (golang-net-v0.33.0_GH0.tar.gz) = 675e0ceaf54baf4f6e2a5152fe148906119c97e7b1d37d1c44ec2621faeab0e8
+SIZE (golang-net-v0.33.0_GH0.tar.gz) = 1466426
+SHA256 (golang-sys-v0.28.0_GH0.tar.gz) = 62726b1ccbb09c7e8de2215756a26012751bdded12b5bacc6de83296db694ebf
+SIZE (golang-sys-v0.28.0_GH0.tar.gz) = 1519898
+SHA256 (golang-term-v0.27.0_GH0.tar.gz) = 4053cac47f4fcd6e38fe80ed4e52a10550681109a09ff7a6cabdb6e1af6bb5a6
+SIZE (golang-term-v0.27.0_GH0.tar.gz) = 14689
SHA256 (google-uuid-v1.6.0_GH0.tar.gz) = ee63376b5675376c60e055ed66e5f3651ccc703bd580c022b8ad00cea309252d
SIZE (google-uuid-v1.6.0_GH0.tar.gz) = 20896
SHA256 (gorilla-websocket-v1.5.0_GH0.tar.gz) = 5d86f9e1c76ff7ceca0747f78b79864fbaec9d440f4fdb03197466e5102a86b0
@@ -25,8 +25,8 @@ SHA256 (jech-cert-f491cf43a77d_GH0.tar.gz) = a31c5dc063e19e49e27454e9ffd12fd0895
SIZE (jech-cert-f491cf43a77d_GH0.tar.gz) = 3756
SHA256 (jech-samplebuilder-6cbba09fc1c9_GH0.tar.gz) = 08082afa77f3083c0b15ed09fe27d43c525bc31af3662e13288dd167a609c2ad
SIZE (jech-samplebuilder-6cbba09fc1c9_GH0.tar.gz) = 12428
-SHA256 (pion-datachannel-v1.5.9_GH0.tar.gz) = b23a0532f6a70ba3eae2a8052285f01545866fb56dd30cb12cd1f616bbb8eb8f
-SIZE (pion-datachannel-v1.5.9_GH0.tar.gz) = 17018
+SHA256 (pion-datachannel-v1.5.10_GH0.tar.gz) = 07b7d4decbc83e84f00ce2c1587f55579aa5c018379c8e17c7d6c681df5c8eb6
+SIZE (pion-datachannel-v1.5.10_GH0.tar.gz) = 17048
SHA256 (pion-dtls-v2.2.12_GH0.tar.gz) = 17d45dba2712a9fff680f1e441b26566daf7f9103656fd3f65d05fda0b5e0009
SIZE (pion-dtls-v2.2.12_GH0.tar.gz) = 152165
SHA256 (pion-ice-v2.3.37_GH0.tar.gz) = e935cbc70fb9344c5407b4a7cd3c7299d2db3bd4a5785346b040a102d5a5380d
@@ -39,12 +39,12 @@ SHA256 (pion-mdns-v0.0.12_GH0.tar.gz) = d291ea4260996731e09103beb498f6e1b9fd3643
SIZE (pion-mdns-v0.0.12_GH0.tar.gz) = 17490
SHA256 (pion-randutil-v0.1.0_GH0.tar.gz) = 4b0301915ebbfa77c8621cebf99c6c7d71651762a33ce4fa4e6af8994ecd4993
SIZE (pion-randutil-v0.1.0_GH0.tar.gz) = 7521
-SHA256 (pion-rtcp-v1.2.14_GH0.tar.gz) = ab0674ed126edfafc8dcb1c70d269cf04d6498983e5ebe92c9c8ea776234d660
-SIZE (pion-rtcp-v1.2.14_GH0.tar.gz) = 59682
-SHA256 (pion-rtp-v1.8.9_GH0.tar.gz) = c4174853bc2cd78193621e7c96b72ba5f52edaa88e98b8e79b531bc943f225fd
-SIZE (pion-rtp-v1.8.9_GH0.tar.gz) = 62171
-SHA256 (pion-sctp-v1.8.33_GH0.tar.gz) = ffeac32cbdc684462701aae276106e1912b86b470242b886e1a8866e4a74c51b
-SIZE (pion-sctp-v1.8.33_GH0.tar.gz) = 94390
+SHA256 (pion-rtcp-v1.2.15_GH0.tar.gz) = b3032a27547fe6a2d2468db5925399b8e13aec3770788db98b91c327bb54695f
+SIZE (pion-rtcp-v1.2.15_GH0.tar.gz) = 61468
+SHA256 (pion-rtp-v1.8.10_GH0.tar.gz) = f998acdb35dc3c8741fc4198b240342bc549777db6414adc75e70765e1cac57a
+SIZE (pion-rtp-v1.8.10_GH0.tar.gz) = 62142
+SHA256 (pion-sctp-v1.8.35_GH0.tar.gz) = 780d450604fd9eafcc1f2b93f42d0c0ca690be8c57770e6a3cc817270ac37821
+SIZE (pion-sctp-v1.8.35_GH0.tar.gz) = 96553
SHA256 (pion-sdp-v3.0.9_GH0.tar.gz) = d0de98412c90f90379297f00c7b766a8bbf129672d2e896d3bcd780d37f35e60
SIZE (pion-sdp-v3.0.9_GH0.tar.gz) = 28358
SHA256 (pion-srtp-v2.0.20_GH0.tar.gz) = 8156afe373b0f6f43dbbbd56deca6b32f039d9995d0b6bd3c2757c1630b5443e
@@ -53,13 +53,15 @@ SHA256 (pion-stun-v0.6.1_GH0.tar.gz) = 6abda07e177b9f65412e3b11dae6a35663869ebec
SIZE (pion-stun-v0.6.1_GH0.tar.gz) = 91808
SHA256 (pion-transport-v2.2.10_GH0.tar.gz) = 112640b7644824e3e63426bfd23712bcaadab670e3171f86c34948863b5ff0ff
SIZE (pion-transport-v2.2.10_GH0.tar.gz) = 90002
+SHA256 (pion-transport-v3.0.7_GH0.tar.gz) = dca2f4ede133623bfb1f2d1a055e500c80ef3faa39ad9db4d45086d60c7458b5
+SIZE (pion-transport-v3.0.7_GH0.tar.gz) = 85680
SHA256 (pion-turn-v2.1.6_GH0.tar.gz) = 243841be67659ad71437e818b82c4032731cf1a3ad73e948bf3abbe27a5addb5
SIZE (pion-turn-v2.1.6_GH0.tar.gz) = 131516
-SHA256 (pion-webrtc-v3.3.4_GH0.tar.gz) = 90ffd02e21676079b5e4a50ac4a310bff8f707fdc4d75812c347d26460c22286
-SIZE (pion-webrtc-v3.3.4_GH0.tar.gz) = 386093
+SHA256 (pion-webrtc-v3.3.5_GH0.tar.gz) = 93ff5d7860d94a1411bd532d9d4e1affb0e8d99e83e36c2a7596d753438e2cb8
+SIZE (pion-webrtc-v3.3.5_GH0.tar.gz) = 386477
SHA256 (pmezard-go-difflib-v1.0.0_GH0.tar.gz) = 28f3dc1b5c0efd61203ab07233f774740d3bf08da4d8153fb5310db6cea0ebda
SIZE (pmezard-go-difflib-v1.0.0_GH0.tar.gz) = 11398
-SHA256 (stretchr-testify-v1.9.0_GH0.tar.gz) = ee651d4d4427d55096007190398102383498e6b5cf97ea9e89ad6e72b4115fbb
-SIZE (stretchr-testify-v1.9.0_GH0.tar.gz) = 108663
+SHA256 (stretchr-testify-v1.10.0_GH0.tar.gz) = 06af5143ab5fc8f2fbf3d1420a5f002f6383cd7de911698dbd1822beacb27684
+SIZE (stretchr-testify-v1.10.0_GH0.tar.gz) = 112732
SHA256 (wlynxg-anet-v0.0.5_GH0.tar.gz) = bf9a401124ec58f00413b5597fc7f9ced9abd3314ec62ce49021c4c7b023d47e
SIZE (wlynxg-anet-v0.0.5_GH0.tar.gz) = 5475910
diff --git a/www/iridium/Makefile b/www/iridium/Makefile
index 77f52b16e365..ace3050434e2 100644
--- a/www/iridium/Makefile
+++ b/www/iridium/Makefile
@@ -1,6 +1,5 @@
PORTNAME= iridium
-PORTVERSION= 2025.05.136.1
-PORTREVISION= 1
+PORTVERSION= 2025.05.136.2
PULSEMV= 16
PULSEV= ${PULSEMV}.1
CATEGORIES= www wayland
diff --git a/www/iridium/distinfo b/www/iridium/distinfo
index 803215ab849b..58d0b1608e14 100644
--- a/www/iridium/distinfo
+++ b/www/iridium/distinfo
@@ -1,5 +1,5 @@
-TIMESTAMP = 1746686164
-SHA256 (iridium-browser-2025.05.136.1.tar.xz) = 5baa038eeafcc04a199cff7f512839b9ac3fdac71fe496af9ff3c8544f51f9ae
-SIZE (iridium-browser-2025.05.136.1.tar.xz) = 3044399212
+TIMESTAMP = 1747324897
+SHA256 (iridium-browser-2025.05.136.2.tar.xz) = 49c4e1db1c81b78f83c0eb4b1e3a85daba92a01b741e857bf9d56e5fc33d0c82
+SIZE (iridium-browser-2025.05.136.2.tar.xz) = 3044410956
SHA256 (pulseaudio-16.1.tar.gz) = 027266c62f2a84422ac45fa721a649508f0f1628fb1fd9242315ac54ce2d7c92
SIZE (pulseaudio-16.1.tar.gz) = 2763111
diff --git a/www/iridium/files/patch-third__party_blink_renderer_platform_runtime__enabled__features.json5 b/www/iridium/files/patch-third__party_blink_renderer_platform_runtime__enabled__features.json5
index 4ffb0ebffc40..08dd9c45781c 100644
--- a/www/iridium/files/patch-third__party_blink_renderer_platform_runtime__enabled__features.json5
+++ b/www/iridium/files/patch-third__party_blink_renderer_platform_runtime__enabled__features.json5
@@ -1,4 +1,4 @@
---- third_party/blink/renderer/platform/runtime_enabled_features.json5.orig 2025-05-07 06:48:23 UTC
+--- third_party/blink/renderer/platform/runtime_enabled_features.json5.orig 2025-05-15 16:06:59 UTC
+++ third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -434,7 +434,7 @@
name: "AppTitle",
@@ -45,7 +45,7 @@
status: "stable",
public: true,
base_feature: "none",
-@@ -4636,7 +4636,7 @@
+@@ -4635,7 +4635,7 @@
name: "UnrestrictedSharedArrayBuffer",
base_feature: "none",
origin_trial_feature_name: "UnrestrictedSharedArrayBuffer",
@@ -54,7 +54,7 @@
},
// Enables using policy-controlled feature "usb-unrestricted" to allow
// isolated context to access protected USB interface classes and to
-@@ -4811,7 +4811,7 @@
+@@ -4810,7 +4810,7 @@
{
name: "WebAppScopeExtensions",
origin_trial_feature_name: "WebAppScopeExtensions",
@@ -63,7 +63,7 @@
status: "experimental",
base_feature: "none",
},
-@@ -5086,7 +5086,7 @@
+@@ -5085,7 +5085,7 @@
{
name: "WebIdentityDigitalCredentials",
origin_trial_feature_name: "WebIdentityDigitalCredentials",
diff --git a/www/librewolf/Makefile b/www/librewolf/Makefile
index ebd4edfe5e19..15e83127c5e4 100644
--- a/www/librewolf/Makefile
+++ b/www/librewolf/Makefile
@@ -1,8 +1,7 @@
PORTNAME= librewolf
-DISTVERSION= 138.0.1
-LWPATCH= -2
+DISTVERSION= 138.0.3
+LWPATCH= -1
DISTVERSIONSUFFIX= ${LWPATCH}.source
-PORTREVISION= 1
CATEGORIES= www wayland
MASTER_SITES= https://gitlab.com/api/v4/projects/32320088/packages/generic/${PORTNAME}-source/${DISTVERSION}${LWPATCH}/
diff --git a/www/librewolf/distinfo b/www/librewolf/distinfo
index 31195b372818..5848fa1442f7 100644
--- a/www/librewolf/distinfo
+++ b/www/librewolf/distinfo
@@ -1,3 +1,3 @@
-TIMESTAMP = 1746445113
-SHA256 (librewolf-138.0.1-2.source.tar.gz) = 308ac7a2d890bb798d3058dcf89415ccfb37e80e951f141b13c2ca98a758efd2
-SIZE (librewolf-138.0.1-2.source.tar.gz) = 1019041631
+TIMESTAMP = 1747328459
+SHA256 (librewolf-138.0.3-1.source.tar.gz) = 0a849bb4cb4448004451f1af87c12a951d782048e8668b9b6754246089c45dcb
+SIZE (librewolf-138.0.3-1.source.tar.gz) = 1019083591
diff --git a/www/nextcloud-calendar/Makefile b/www/nextcloud-calendar/Makefile
index 8062dfb93509..84a890b3afb5 100644
--- a/www/nextcloud-calendar/Makefile
+++ b/www/nextcloud-calendar/Makefile
@@ -1,5 +1,5 @@
PORTNAME= calendar
-PORTVERSION= 5.2.3
+PORTVERSION= 5.2.4
DISTVERSIONPREFIX= v
CATEGORIES= www
diff --git a/www/nextcloud-calendar/distinfo b/www/nextcloud-calendar/distinfo
index a681a6b91bfa..63fe37edd4ed 100644
--- a/www/nextcloud-calendar/distinfo
+++ b/www/nextcloud-calendar/distinfo
@@ -1,3 +1,3 @@
-TIMESTAMP = 1746950468
-SHA256 (nextcloud/calendar-v5.2.3.tar.gz) = 3647d69f4e9218e1cc50da85bc9021ef7968709e20a208a5deeb01ef4673fcc8
-SIZE (nextcloud/calendar-v5.2.3.tar.gz) = 19796857
+TIMESTAMP = 1747333671
+SHA256 (nextcloud/calendar-v5.2.4.tar.gz) = cff04c29acbd163f9a232a4f03d71b109e9d701d37a063e1cb64d218725e473d
+SIZE (nextcloud/calendar-v5.2.4.tar.gz) = 19795163
diff --git a/www/nextcloud-contacts/Makefile b/www/nextcloud-contacts/Makefile
index 95f44662bbe9..328bd28a0f86 100644
--- a/www/nextcloud-contacts/Makefile
+++ b/www/nextcloud-contacts/Makefile
@@ -1,5 +1,5 @@
PORTNAME= contacts
-PORTVERSION= 7.0.6
+PORTVERSION= 7.1.0
DISTVERSIONPREFIX= v
CATEGORIES= www
diff --git a/www/nextcloud-contacts/distinfo b/www/nextcloud-contacts/distinfo
index 6b3df11045b3..c15f6bcd93a0 100644
--- a/www/nextcloud-contacts/distinfo
+++ b/www/nextcloud-contacts/distinfo
@@ -1,3 +1,3 @@
-TIMESTAMP = 1745079799
-SHA256 (nextcloud/contacts-v7.0.6.tar.gz) = dc6d5d8bf3e738020c2f6bf02a0966b8c029be7f3e9d762376a9f24924a82c32
-SIZE (nextcloud/contacts-v7.0.6.tar.gz) = 4327344
+TIMESTAMP = 1747333704
+SHA256 (nextcloud/contacts-v7.1.0.tar.gz) = 39839b18810056204c59eb0bfe436fe051ceed249aef7add563925c2ec8f4ab6
+SIZE (nextcloud/contacts-v7.1.0.tar.gz) = 4354560
diff --git a/www/nextcloud/Makefile b/www/nextcloud/Makefile
index aeac60e9b5de..0c9d210db4d2 100644
--- a/www/nextcloud/Makefile
+++ b/www/nextcloud/Makefile
@@ -1,5 +1,5 @@
PORTNAME= nextcloud
-PORTVERSION= 31.0.4
+PORTVERSION= 31.0.5
CATEGORIES= www
MASTER_SITES= https://download.nextcloud.com/server/releases/
PKGNAMESUFFIX= ${PHP_PKGNAMESUFFIX}
diff --git a/www/nextcloud/distinfo b/www/nextcloud/distinfo
index 68bc03dbd0bb..97eb88f9a750 100644
--- a/www/nextcloud/distinfo
+++ b/www/nextcloud/distinfo
@@ -1,3 +1,3 @@
-TIMESTAMP = 1745150519
-SHA256 (nextcloud/nextcloud-31.0.4.tar.bz2) = a47541566d5c6ac6f63e4f617e27da295156da47daa2cd22eee3400fd2ad1251
-SIZE (nextcloud/nextcloud-31.0.4.tar.bz2) = 227351477
+TIMESTAMP = 1747332904
+SHA256 (nextcloud/nextcloud-31.0.5.tar.bz2) = 2228b8f524dcd87f08a2a9281d41b04f5cb500b7624bc8c8e07b8e3039061503
+SIZE (nextcloud/nextcloud-31.0.5.tar.bz2) = 226737152
diff --git a/www/py-dj50-django-auth-ldap/Makefile b/www/py-dj50-django-auth-ldap/Makefile
index d48e46991bd5..eaa0337951dc 100644
--- a/www/py-dj50-django-auth-ldap/Makefile
+++ b/www/py-dj50-django-auth-ldap/Makefile
@@ -1,5 +1,5 @@
PORTNAME= django-auth-ldap
-PORTVERSION= 5.1.0
+PORTVERSION= 5.2.0
CATEGORIES= www security python
MASTER_SITES= PYPI
PKGNAMEPREFIX= ${PYTHON_PKGNAMEPREFIX}dj50-
diff --git a/www/py-dj50-django-auth-ldap/distinfo b/www/py-dj50-django-auth-ldap/distinfo
index 2ae0a3f4baa0..d60b5a523112 100644
--- a/www/py-dj50-django-auth-ldap/distinfo
+++ b/www/py-dj50-django-auth-ldap/distinfo
@@ -1,3 +1,3 @@
-TIMESTAMP = 1730477310
-SHA256 (django_auth_ldap-5.1.0.tar.gz) = 9c607e8d9c53cf2a0ccafbe0acfc33eb1d1fd474c46ec52d30aee0dca1da9668
-SIZE (django_auth_ldap-5.1.0.tar.gz) = 55059
+TIMESTAMP = 1747314334
+SHA256 (django_auth_ldap-5.2.0.tar.gz) = 08ba6efc0340d9874725a962311b14991e29a33593eb150a8fb640709dbfa80f
+SIZE (django_auth_ldap-5.2.0.tar.gz) = 55287
diff --git a/www/py-dj51-django-auth-ldap/Makefile b/www/py-dj51-django-auth-ldap/Makefile
index 94a842eefd8b..b71226b9f650 100644
--- a/www/py-dj51-django-auth-ldap/Makefile
+++ b/www/py-dj51-django-auth-ldap/Makefile
@@ -1,5 +1,5 @@
PORTNAME= django-auth-ldap
-PORTVERSION= 5.1.0
+PORTVERSION= 5.2.0
CATEGORIES= www security python
MASTER_SITES= PYPI
PKGNAMEPREFIX= ${PYTHON_PKGNAMEPREFIX}dj51-
diff --git a/www/py-dj51-django-auth-ldap/distinfo b/www/py-dj51-django-auth-ldap/distinfo
index 2ae0a3f4baa0..d60b5a523112 100644
--- a/www/py-dj51-django-auth-ldap/distinfo
+++ b/www/py-dj51-django-auth-ldap/distinfo
@@ -1,3 +1,3 @@
-TIMESTAMP = 1730477310
-SHA256 (django_auth_ldap-5.1.0.tar.gz) = 9c607e8d9c53cf2a0ccafbe0acfc33eb1d1fd474c46ec52d30aee0dca1da9668
-SIZE (django_auth_ldap-5.1.0.tar.gz) = 55059
+TIMESTAMP = 1747314334
+SHA256 (django_auth_ldap-5.2.0.tar.gz) = 08ba6efc0340d9874725a962311b14991e29a33593eb150a8fb640709dbfa80f
+SIZE (django_auth_ldap-5.2.0.tar.gz) = 55287
diff --git a/www/py-django-auth-ldap/Makefile b/www/py-django-auth-ldap/Makefile
index 8e92221e47f5..c27d62dce257 100644
--- a/www/py-django-auth-ldap/Makefile
+++ b/www/py-django-auth-ldap/Makefile
@@ -1,5 +1,5 @@
PORTNAME= django-auth-ldap
-PORTVERSION= 5.1.0
+PORTVERSION= 5.2.0
CATEGORIES= www security python
MASTER_SITES= PYPI
PKGNAMEPREFIX= ${PYTHON_PKGNAMEPREFIX}
@@ -18,7 +18,7 @@ BUILD_DEPENDS= ${PY_SETUPTOOLS} \
RUN_DEPENDS= ${PYTHON_PKGNAMEPREFIX}django42>=4.2:www/py-django42@${PY_FLAVOR} \
${PYTHON_PKGNAMEPREFIX}python-ldap>=3.1:net/py-python-ldap@${PY_FLAVOR}
-USES= python:3.9+
+USES= python
USE_PYTHON= autoplist concurrent pep517
NO_ARCH= yes
diff --git a/www/py-django-auth-ldap/distinfo b/www/py-django-auth-ldap/distinfo
index 2ae0a3f4baa0..d60b5a523112 100644
--- a/www/py-django-auth-ldap/distinfo
+++ b/www/py-django-auth-ldap/distinfo
@@ -1,3 +1,3 @@
-TIMESTAMP = 1730477310
-SHA256 (django_auth_ldap-5.1.0.tar.gz) = 9c607e8d9c53cf2a0ccafbe0acfc33eb1d1fd474c46ec52d30aee0dca1da9668
-SIZE (django_auth_ldap-5.1.0.tar.gz) = 55059
+TIMESTAMP = 1747314334
+SHA256 (django_auth_ldap-5.2.0.tar.gz) = 08ba6efc0340d9874725a962311b14991e29a33593eb150a8fb640709dbfa80f
+SIZE (django_auth_ldap-5.2.0.tar.gz) = 55287
diff --git a/www/ungoogled-chromium/Makefile b/www/ungoogled-chromium/Makefile
index 486a71a46852..82ad56dc48d0 100644
--- a/www/ungoogled-chromium/Makefile
+++ b/www/ungoogled-chromium/Makefile
@@ -1,6 +1,5 @@
PORTNAME= ungoogled-chromium
-PORTVERSION= 136.0.7103.92
-PORTREVISION= 1
+PORTVERSION= 136.0.7103.113
PULSEMV= 16
PULSEV= ${PULSEMV}.1
UGVERSION= ${DISTVERSION}-1
diff --git a/www/ungoogled-chromium/distinfo b/www/ungoogled-chromium/distinfo
index ff9869865cd1..f53ddc783f79 100644
--- a/www/ungoogled-chromium/distinfo
+++ b/www/ungoogled-chromium/distinfo
@@ -1,9 +1,9 @@
-TIMESTAMP = 1746691040
-SHA256 (chromium-136.0.7103.92.tar.xz) = 3fa7f88ef186566948367bf1e9a9f0612e753fc69285c1654728f6a015cd4cf2
-SIZE (chromium-136.0.7103.92.tar.xz) = 7188412240
+TIMESTAMP = 1747298437
+SHA256 (chromium-136.0.7103.113.tar.xz) = 7c765bd13df842a28bb52279b8d711411ac6082151473e07bd70b9a482c0a0ac
+SIZE (chromium-136.0.7103.113.tar.xz) = 7196537592
SHA256 (pulseaudio-16.1.tar.gz) = 027266c62f2a84422ac45fa721a649508f0f1628fb1fd9242315ac54ce2d7c92
SIZE (pulseaudio-16.1.tar.gz) = 2763111
-SHA256 (chromium-136.0.7103.92-testdata.tar.xz) = 6e5bb3fba5b61ffc9e91b9d2fc9cc758bebe4d16806a68b1a32b189193c78256
-SIZE (chromium-136.0.7103.92-testdata.tar.xz) = 651393856
-SHA256 (ungoogled-software-ungoogled-chromium-136.0.7103.92-136.0.7103.92-1_GH0.tar.gz) = d256643a26d536a5079441e63fd4c8cda0e073702665605b40c5ce1d5b18bcbe
-SIZE (ungoogled-software-ungoogled-chromium-136.0.7103.92-136.0.7103.92-1_GH0.tar.gz) = 633266
+SHA256 (chromium-136.0.7103.113-testdata.tar.xz) = cbf264643986db5b7aa91843ea64a1b9e23d00bb226b234d4f60788469a58ef8
+SIZE (chromium-136.0.7103.113-testdata.tar.xz) = 651614116
+SHA256 (ungoogled-software-ungoogled-chromium-136.0.7103.113-136.0.7103.113-1_GH0.tar.gz) = ab4c1b21292b860eaa750d3fb9ee73dae58a86d2dd59d4e41e06102e8c9f635a
+SIZE (ungoogled-software-ungoogled-chromium-136.0.7103.113-136.0.7103.113-1_GH0.tar.gz) = 633301
diff --git a/www/ungoogled-chromium/files/patch-third__party_blink_renderer_platform_runtime__enabled__features.json5 b/www/ungoogled-chromium/files/patch-third__party_blink_renderer_platform_runtime__enabled__features.json5
index 9a37800799e6..9b0ab86d6d91 100644
--- a/www/ungoogled-chromium/files/patch-third__party_blink_renderer_platform_runtime__enabled__features.json5
+++ b/www/ungoogled-chromium/files/patch-third__party_blink_renderer_platform_runtime__enabled__features.json5
@@ -1,4 +1,4 @@
---- third_party/blink/renderer/platform/runtime_enabled_features.json5.orig 2025-05-06 12:23:00 UTC
+--- third_party/blink/renderer/platform/runtime_enabled_features.json5.orig 2025-05-15 08:53:47 UTC
+++ third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -434,7 +434,7 @@
name: "AppTitle",
@@ -45,7 +45,7 @@
status: "stable",
public: true,
base_feature: "none",
-@@ -4645,7 +4645,7 @@
+@@ -4644,7 +4644,7 @@
name: "UnrestrictedSharedArrayBuffer",
base_feature: "none",
origin_trial_feature_name: "UnrestrictedSharedArrayBuffer",
@@ -54,7 +54,7 @@
},
// Enables using policy-controlled feature "usb-unrestricted" to allow
// isolated context to access protected USB interface classes and to
-@@ -4820,7 +4820,7 @@
+@@ -4819,7 +4819,7 @@
{
name: "WebAppScopeExtensions",
origin_trial_feature_name: "WebAppScopeExtensions",
@@ -63,7 +63,7 @@
status: "experimental",
base_feature: "none",
},
-@@ -5095,7 +5095,7 @@
+@@ -5094,7 +5094,7 @@
{
name: "WebIdentityDigitalCredentials",
origin_trial_feature_name: "WebIdentityDigitalCredentials",